Merge tag 'renesas-fixes-for-v6.6-tag1' of git://git.kernel.org/pub/scm/linux/kernel...
authorArnd Bergmann <arnd@arndb.de>
Fri, 6 Oct 2023 20:46:30 +0000 (22:46 +0200)
committerArnd Bergmann <arnd@arndb.de>
Fri, 6 Oct 2023 20:46:31 +0000 (22:46 +0200)
Renesas fixes for v6.6

  - Fix RISC-V multi-platform kernels by excluding RZ/Five.

* tag 'renesas-fixes-for-v6.6-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel:
  soc: renesas: Make ARCH_R9A07G043 (riscv version) depend on NONPORTABLE

Link: https://lore.kernel.org/r/cover.1696578170.git.geert+renesas@glider.be
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
834 files changed:
Documentation/arch/arm64/cpu-feature-registers.rst
Documentation/arch/arm64/elf_hwcaps.rst
Documentation/arch/loongarch/introduction.rst
Documentation/filesystems/btrfs.rst
Documentation/networking/ax25.rst
Documentation/process/embargoed-hardware-issues.rst
Documentation/sound/designs/midi-2.0.rst
Documentation/translations/zh_CN/arch/loongarch/introduction.rst
MAINTAINERS
Makefile
arch/arm/xen/enlighten.c
arch/arm64/boot/dts/mediatek/mt7622.dtsi
arch/arm64/boot/dts/mediatek/mt7986a.dtsi
arch/arm64/boot/dts/mediatek/mt8195-demo.dts
arch/arm64/boot/dts/mediatek/mt8195.dtsi
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/kvm_hyp.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kvm/hyp/include/nvhe/ffa.h
arch/arm64/kvm/hyp/nvhe/ffa.c
arch/arm64/kvm/hyp/nvhe/hyp-init.S
arch/arm64/kvm/hyp/nvhe/hyp-main.c
arch/arm64/kvm/hyp/nvhe/psci-relay.c
arch/arm64/kvm/mmu.c
arch/arm64/tools/sysreg
arch/ia64/kernel/acpi.c
arch/loongarch/include/asm/addrspace.h
arch/loongarch/include/asm/exception.h [new file with mode: 0644]
arch/loongarch/include/asm/kasan.h
arch/loongarch/include/asm/smp.h
arch/loongarch/kernel/Makefile
arch/loongarch/kernel/acpi.c
arch/loongarch/kernel/mem.c
arch/loongarch/kernel/module-sections.c
arch/loongarch/kernel/process.c
arch/loongarch/kernel/relocate_kernel.S
arch/loongarch/kernel/signal.c
arch/loongarch/kernel/smp.c
arch/loongarch/kernel/syscall.c
arch/loongarch/kernel/time.c
arch/loongarch/kernel/topology.c
arch/loongarch/kernel/traps.c
arch/loongarch/kernel/vmlinux.lds.S
arch/loongarch/mm/fault.c
arch/loongarch/mm/hugetlbpage.c
arch/loongarch/mm/ioremap.c
arch/loongarch/mm/kasan_init.c
arch/loongarch/mm/tlb.c
arch/parisc/include/asm/cache.h
arch/parisc/include/asm/mckinley.h [deleted file]
arch/parisc/include/asm/pdc.h
arch/parisc/include/asm/processor.h
arch/parisc/include/asm/ropes.h
arch/parisc/include/asm/shmparam.h
arch/parisc/kernel/asm-offsets.c
arch/parisc/kernel/cache.c
arch/parisc/kernel/drivers.c
arch/parisc/kernel/firmware.c
arch/parisc/kernel/head.S
arch/parisc/kernel/irq.c
arch/parisc/kernel/processor.c
arch/parisc/kernel/vmlinux.lds.S
arch/parisc/mm/init.c
arch/powerpc/Kconfig
arch/powerpc/kernel/hw_breakpoint.c
arch/powerpc/kernel/hw_breakpoint_constraints.c
arch/powerpc/kernel/traps.c
arch/powerpc/perf/hv-24x7.c
arch/powerpc/platforms/82xx/Kconfig
arch/riscv/include/asm/errata_list.h
arch/riscv/kernel/elf_kexec.c
arch/riscv/kvm/vcpu_onereg.c
arch/s390/configs/debug_defconfig
arch/s390/configs/defconfig
arch/s390/configs/zfcpdump_defconfig
arch/s390/kernel/cert_store.c
arch/sh/mm/ioremap.c
arch/x86/Kconfig
arch/x86/boot/compressed/ident_map_64.c
arch/x86/entry/common.c
arch/x86/include/asm/boot.h
arch/x86/include/asm/efi.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/linkage.h
arch/x86/include/asm/mmu_context.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/xen/hypervisor.h
arch/x86/kernel/alternative.c
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/callthunks.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/process.c
arch/x86/kernel/setup.c
arch/x86/kernel/shstk.c
arch/x86/kernel/smpboot.c
arch/x86/kvm/mmu/mmu.c
arch/x86/kvm/mmu/mmu_internal.h
arch/x86/kvm/mmu/tdp_mmu.c
arch/x86/kvm/mmu/tdp_mmu.h
arch/x86/kvm/svm/sev.c
arch/x86/kvm/svm/svm.c
arch/x86/kvm/svm/svm.h
arch/x86/kvm/x86.c
arch/x86/lib/memcpy_64.S
arch/x86/lib/memmove_64.S
arch/x86/lib/memset_64.S
arch/x86/lib/putuser.S
arch/x86/platform/efi/efi_32.c
arch/x86/platform/efi/efi_64.c
arch/x86/purgatory/Makefile
arch/x86/xen/efi.c
arch/x86/xen/enlighten.c
arch/x86/xen/enlighten_hvm.c
arch/x86/xen/enlighten_pv.c
arch/x86/xen/mmu_pv.c
arch/x86/xen/multicalls.h
block/blk-mq.c
crypto/sm2.c
drivers/Makefile
drivers/accel/ivpu/ivpu_hw_40xx.c
drivers/acpi/processor_pdc.c
drivers/acpi/thermal.c
drivers/ata/ahci.c
drivers/ata/libahci.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-sata.c
drivers/ata/pata_parport/comm.c
drivers/ata/sata_mv.c
drivers/base/core.c
drivers/char/agp/parisc-agp.c
drivers/char/tpm/tpm-chip.c
drivers/comedi/Kconfig
drivers/cxl/acpi.c
drivers/cxl/core/mbox.c
drivers/cxl/core/port.c
drivers/cxl/core/region.c
drivers/cxl/pci.c
drivers/firewire/core-device.c
drivers/firewire/core-topology.c
drivers/firmware/cirrus/cs_dsp.c
drivers/firmware/efi/efi.c
drivers/firmware/efi/libstub/unaccepted_memory.c
drivers/genpd/Makefile [deleted file]
drivers/genpd/actions/Makefile [deleted file]
drivers/genpd/actions/owl-sps-helper.c [deleted file]
drivers/genpd/actions/owl-sps.c [deleted file]
drivers/genpd/amlogic/Makefile [deleted file]
drivers/genpd/amlogic/meson-ee-pwrc.c [deleted file]
drivers/genpd/amlogic/meson-gx-pwrc-vpu.c [deleted file]
drivers/genpd/amlogic/meson-secure-pwrc.c [deleted file]
drivers/genpd/apple/Makefile [deleted file]
drivers/genpd/apple/pmgr-pwrstate.c [deleted file]
drivers/genpd/bcm/Makefile [deleted file]
drivers/genpd/bcm/bcm-pmb.c [deleted file]
drivers/genpd/bcm/bcm2835-power.c [deleted file]
drivers/genpd/bcm/bcm63xx-power.c [deleted file]
drivers/genpd/bcm/raspberrypi-power.c [deleted file]
drivers/genpd/imx/Makefile [deleted file]
drivers/genpd/imx/gpc.c [deleted file]
drivers/genpd/imx/gpcv2.c [deleted file]
drivers/genpd/imx/imx8m-blk-ctrl.c [deleted file]
drivers/genpd/imx/imx8mp-blk-ctrl.c [deleted file]
drivers/genpd/imx/imx93-blk-ctrl.c [deleted file]
drivers/genpd/imx/imx93-pd.c [deleted file]
drivers/genpd/imx/scu-pd.c [deleted file]
drivers/genpd/mediatek/Makefile [deleted file]
drivers/genpd/mediatek/mt6795-pm-domains.h [deleted file]
drivers/genpd/mediatek/mt8167-pm-domains.h [deleted file]
drivers/genpd/mediatek/mt8173-pm-domains.h [deleted file]
drivers/genpd/mediatek/mt8183-pm-domains.h [deleted file]
drivers/genpd/mediatek/mt8186-pm-domains.h [deleted file]
drivers/genpd/mediatek/mt8188-pm-domains.h [deleted file]
drivers/genpd/mediatek/mt8192-pm-domains.h [deleted file]
drivers/genpd/mediatek/mt8195-pm-domains.h [deleted file]
drivers/genpd/mediatek/mtk-pm-domains.c [deleted file]
drivers/genpd/mediatek/mtk-pm-domains.h [deleted file]
drivers/genpd/mediatek/mtk-scpsys.c [deleted file]
drivers/genpd/qcom/Makefile [deleted file]
drivers/genpd/qcom/cpr.c [deleted file]
drivers/genpd/qcom/rpmhpd.c [deleted file]
drivers/genpd/qcom/rpmpd.c [deleted file]
drivers/genpd/renesas/Makefile [deleted file]
drivers/genpd/renesas/r8a7742-sysc.c [deleted file]
drivers/genpd/renesas/r8a7743-sysc.c [deleted file]
drivers/genpd/renesas/r8a7745-sysc.c [deleted file]
drivers/genpd/renesas/r8a77470-sysc.c [deleted file]
drivers/genpd/renesas/r8a774a1-sysc.c [deleted file]
drivers/genpd/renesas/r8a774b1-sysc.c [deleted file]
drivers/genpd/renesas/r8a774c0-sysc.c [deleted file]
drivers/genpd/renesas/r8a774e1-sysc.c [deleted file]
drivers/genpd/renesas/r8a7779-sysc.c [deleted file]
drivers/genpd/renesas/r8a7790-sysc.c [deleted file]
drivers/genpd/renesas/r8a7791-sysc.c [deleted file]
drivers/genpd/renesas/r8a7792-sysc.c [deleted file]
drivers/genpd/renesas/r8a7794-sysc.c [deleted file]
drivers/genpd/renesas/r8a7795-sysc.c [deleted file]
drivers/genpd/renesas/r8a7796-sysc.c [deleted file]
drivers/genpd/renesas/r8a77965-sysc.c [deleted file]
drivers/genpd/renesas/r8a77970-sysc.c [deleted file]
drivers/genpd/renesas/r8a77980-sysc.c [deleted file]
drivers/genpd/renesas/r8a77990-sysc.c [deleted file]
drivers/genpd/renesas/r8a77995-sysc.c [deleted file]
drivers/genpd/renesas/r8a779a0-sysc.c [deleted file]
drivers/genpd/renesas/r8a779f0-sysc.c [deleted file]
drivers/genpd/renesas/r8a779g0-sysc.c [deleted file]
drivers/genpd/renesas/rcar-gen4-sysc.c [deleted file]
drivers/genpd/renesas/rcar-gen4-sysc.h [deleted file]
drivers/genpd/renesas/rcar-sysc.c [deleted file]
drivers/genpd/renesas/rcar-sysc.h [deleted file]
drivers/genpd/renesas/rmobile-sysc.c [deleted file]
drivers/genpd/rockchip/Makefile [deleted file]
drivers/genpd/rockchip/pm-domains.c [deleted file]
drivers/genpd/samsung/Makefile [deleted file]
drivers/genpd/samsung/exynos-pm-domains.c [deleted file]
drivers/genpd/st/Makefile [deleted file]
drivers/genpd/st/ste-ux500-pm-domain.c [deleted file]
drivers/genpd/starfive/Makefile [deleted file]
drivers/genpd/starfive/jh71xx-pmu.c [deleted file]
drivers/genpd/sunxi/Makefile [deleted file]
drivers/genpd/sunxi/sun20i-ppu.c [deleted file]
drivers/genpd/tegra/Makefile [deleted file]
drivers/genpd/tegra/powergate-bpmp.c [deleted file]
drivers/genpd/ti/Makefile [deleted file]
drivers/genpd/ti/omap_prm.c [deleted file]
drivers/genpd/ti/ti_sci_pm_domains.c [deleted file]
drivers/genpd/xilinx/Makefile [deleted file]
drivers/genpd/xilinx/zynqmp-pm-domains.c [deleted file]
drivers/gpio/gpio-sim.c
drivers/gpio/gpio-tb10x.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.h
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h
drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
drivers/gpu/drm/amd/amdgpu/nbio_v4_3.c
drivers/gpu/drm/amd/amdgpu/soc21.c
drivers/gpu/drm/amd/amdkfd/kfd_crat.c
drivers/gpu/drm/amd/amdkfd/kfd_crat.h
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c
drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c
drivers/gpu/drm/amd/amdkfd/kfd_priv.h
drivers/gpu/drm/amd/amdkfd/kfd_topology.c
drivers/gpu/drm/amd/amdkfd/kfd_topology.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c
drivers/gpu/drm/amd/display/dc/inc/core_types.h
drivers/gpu/drm/amd/display/dc/link/link_factory.c
drivers/gpu/drm/amd/include/kgd_kfd_interface.h
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
drivers/gpu/drm/drm_connector.c
drivers/gpu/drm/drm_exec.c
drivers/gpu/drm/i915/display/intel_bios.c
drivers/gpu/drm/i915/display/intel_bios.h
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/gt/intel_engine_cs.c
drivers/gpu/drm/i915/gt/intel_execlists_submission.c
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/meson/meson_encoder_hdmi.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_exec.c
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_sched.c
drivers/gpu/drm/radeon/radeon_sa.c
drivers/gpu/drm/tests/drm_mm_test.c
drivers/gpu/drm/tiny/gm12u320.c
drivers/gpu/drm/virtio/virtgpu_submit.c
drivers/gpu/drm/vkms/vkms_composer.c
drivers/gpu/drm/vkms/vkms_crtc.c
drivers/gpu/drm/vkms/vkms_drv.h
drivers/hwmon/nct6775-core.c
drivers/i2c/Kconfig
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-aspeed.c
drivers/i2c/busses/i2c-cadence.c
drivers/i2c/busses/i2c-designware-common.c
drivers/i2c/busses/i2c-designware-core.h
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-xiic.c
drivers/i2c/muxes/i2c-demux-pinctrl.c
drivers/i2c/muxes/i2c-mux-gpio.c
drivers/md/dm-core.h
drivers/md/dm-ioctl.c
drivers/md/dm-table.c
drivers/md/dm.c
drivers/md/md.c
drivers/md/md.h
drivers/md/raid1.c
drivers/media/common/videobuf2/frame_vector.c
drivers/media/i2c/imx219.c
drivers/media/i2c/max9286.c
drivers/media/i2c/rdacm21.c
drivers/media/pci/bt8xx/bttv-risc.c
drivers/media/pci/intel/ivsc/Kconfig
drivers/media/platform/marvell/Kconfig
drivers/media/platform/nxp/imx-mipi-csis.c
drivers/media/platform/via/Kconfig
drivers/media/usb/em28xx/Kconfig
drivers/media/usb/go7007/Kconfig
drivers/media/usb/uvc/uvc_ctrl.c
drivers/mfd/cs42l43.c
drivers/net/dsa/sja1105/sja1105.h
drivers/net/dsa/sja1105/sja1105_dynamic_config.c
drivers/net/dsa/sja1105/sja1105_main.c
drivers/net/ethernet/adi/adin1110.c
drivers/net/ethernet/amazon/ena/ena_netdev.c
drivers/net/ethernet/broadcom/asp2/bcmasp.c
drivers/net/ethernet/broadcom/asp2/bcmasp.h
drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/engleder/tsnep_ethtool.c
drivers/net/ethernet/engleder/tsnep_main.c
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
drivers/net/ethernet/huawei/hinic/hinic_port.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
drivers/net/ethernet/intel/iavf/iavf.h
drivers/net/ethernet/intel/iavf/iavf_ethtool.c
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igc/igc_ethtool.c
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/marvell/octeon_ep/octep_main.c
drivers/net/ethernet/marvell/octeon_ep/octep_tx.c
drivers/net/ethernet/marvell/octeon_ep/octep_tx.h
drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mediatek/mtk_ppe_offload.c
drivers/net/ethernet/microchip/vcap/vcap_api.c
drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
drivers/net/ethernet/pensando/ionic/ionic_dev.h
drivers/net/ethernet/pensando/ionic/ionic_txrx.c
drivers/net/ethernet/renesas/rswitch.c
drivers/net/ethernet/renesas/rswitch.h
drivers/net/ethernet/sfc/tc.c
drivers/net/ethernet/sfc/tc_conntrack.c
drivers/net/ethernet/sfc/tc_counters.c
drivers/net/ethernet/sfc/tc_encap_actions.c
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/ti/Kconfig
drivers/net/team/team.c
drivers/net/thunderbolt/main.c
drivers/net/usb/r8152.c
drivers/net/veth.c
drivers/net/vxlan/vxlan_core.c
drivers/nvme/host/core.c
drivers/nvme/host/fc.c
drivers/nvme/host/hwmon.c
drivers/nvme/host/pci.c
drivers/nvme/target/tcp.c
drivers/parisc/ccio-dma.c
drivers/parisc/iommu-helpers.h
drivers/parisc/iosapic.c
drivers/parisc/iosapic_private.h
drivers/parisc/sba_iommu.c
drivers/pci/pcie/aer.c
drivers/pci/pcie/portdrv.h
drivers/platform/mellanox/Kconfig
drivers/platform/mellanox/mlxbf-pmc.c
drivers/platform/mellanox/mlxbf-tmfifo.c
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/intel_scu_ipc.c
drivers/platform/x86/thinkpad_acpi.c
drivers/pmdomain/Makefile [new file with mode: 0644]
drivers/pmdomain/actions/Makefile [new file with mode: 0644]
drivers/pmdomain/actions/owl-sps-helper.c [new file with mode: 0644]
drivers/pmdomain/actions/owl-sps.c [new file with mode: 0644]
drivers/pmdomain/amlogic/Makefile [new file with mode: 0644]
drivers/pmdomain/amlogic/meson-ee-pwrc.c [new file with mode: 0644]
drivers/pmdomain/amlogic/meson-gx-pwrc-vpu.c [new file with mode: 0644]
drivers/pmdomain/amlogic/meson-secure-pwrc.c [new file with mode: 0644]
drivers/pmdomain/apple/Makefile [new file with mode: 0644]
drivers/pmdomain/apple/pmgr-pwrstate.c [new file with mode: 0644]
drivers/pmdomain/bcm/Makefile [new file with mode: 0644]
drivers/pmdomain/bcm/bcm-pmb.c [new file with mode: 0644]
drivers/pmdomain/bcm/bcm2835-power.c [new file with mode: 0644]
drivers/pmdomain/bcm/bcm63xx-power.c [new file with mode: 0644]
drivers/pmdomain/bcm/raspberrypi-power.c [new file with mode: 0644]
drivers/pmdomain/imx/Makefile [new file with mode: 0644]
drivers/pmdomain/imx/gpc.c [new file with mode: 0644]
drivers/pmdomain/imx/gpcv2.c [new file with mode: 0644]
drivers/pmdomain/imx/imx8m-blk-ctrl.c [new file with mode: 0644]
drivers/pmdomain/imx/imx8mp-blk-ctrl.c [new file with mode: 0644]
drivers/pmdomain/imx/imx93-blk-ctrl.c [new file with mode: 0644]
drivers/pmdomain/imx/imx93-pd.c [new file with mode: 0644]
drivers/pmdomain/imx/scu-pd.c [new file with mode: 0644]
drivers/pmdomain/mediatek/Makefile [new file with mode: 0644]
drivers/pmdomain/mediatek/mt6795-pm-domains.h [new file with mode: 0644]
drivers/pmdomain/mediatek/mt8167-pm-domains.h [new file with mode: 0644]
drivers/pmdomain/mediatek/mt8173-pm-domains.h [new file with mode: 0644]
drivers/pmdomain/mediatek/mt8183-pm-domains.h [new file with mode: 0644]
drivers/pmdomain/mediatek/mt8186-pm-domains.h [new file with mode: 0644]
drivers/pmdomain/mediatek/mt8188-pm-domains.h [new file with mode: 0644]
drivers/pmdomain/mediatek/mt8192-pm-domains.h [new file with mode: 0644]
drivers/pmdomain/mediatek/mt8195-pm-domains.h [new file with mode: 0644]
drivers/pmdomain/mediatek/mtk-pm-domains.c [new file with mode: 0644]
drivers/pmdomain/mediatek/mtk-pm-domains.h [new file with mode: 0644]
drivers/pmdomain/mediatek/mtk-scpsys.c [new file with mode: 0644]
drivers/pmdomain/qcom/Makefile [new file with mode: 0644]
drivers/pmdomain/qcom/cpr.c [new file with mode: 0644]
drivers/pmdomain/qcom/rpmhpd.c [new file with mode: 0644]
drivers/pmdomain/qcom/rpmpd.c [new file with mode: 0644]
drivers/pmdomain/renesas/Makefile [new file with mode: 0644]
drivers/pmdomain/renesas/r8a7742-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a7743-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a7745-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a77470-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a774a1-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a774b1-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a774c0-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a774e1-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a7779-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a7790-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a7791-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a7792-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a7794-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a7795-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a7796-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a77965-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a77970-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a77980-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a77990-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a77995-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a779a0-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a779f0-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/r8a779g0-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/rcar-gen4-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/rcar-gen4-sysc.h [new file with mode: 0644]
drivers/pmdomain/renesas/rcar-sysc.c [new file with mode: 0644]
drivers/pmdomain/renesas/rcar-sysc.h [new file with mode: 0644]
drivers/pmdomain/renesas/rmobile-sysc.c [new file with mode: 0644]
drivers/pmdomain/rockchip/Makefile [new file with mode: 0644]
drivers/pmdomain/rockchip/pm-domains.c [new file with mode: 0644]
drivers/pmdomain/samsung/Makefile [new file with mode: 0644]
drivers/pmdomain/samsung/exynos-pm-domains.c [new file with mode: 0644]
drivers/pmdomain/st/Makefile [new file with mode: 0644]
drivers/pmdomain/st/ste-ux500-pm-domain.c [new file with mode: 0644]
drivers/pmdomain/starfive/Makefile [new file with mode: 0644]
drivers/pmdomain/starfive/jh71xx-pmu.c [new file with mode: 0644]
drivers/pmdomain/sunxi/Makefile [new file with mode: 0644]
drivers/pmdomain/sunxi/sun20i-ppu.c [new file with mode: 0644]
drivers/pmdomain/tegra/Makefile [new file with mode: 0644]
drivers/pmdomain/tegra/powergate-bpmp.c [new file with mode: 0644]
drivers/pmdomain/ti/Makefile [new file with mode: 0644]
drivers/pmdomain/ti/omap_prm.c [new file with mode: 0644]
drivers/pmdomain/ti/ti_sci_pm_domains.c [new file with mode: 0644]
drivers/pmdomain/xilinx/Makefile [new file with mode: 0644]
drivers/pmdomain/xilinx/zynqmp-pm-domains.c [new file with mode: 0644]
drivers/regulator/helpers.c
drivers/scsi/iscsi_tcp.c
drivers/scsi/lpfc/lpfc_debugfs.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_nvme.c
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/pm8001/pm8001_hwi.c
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/pm8001/pm80xx_hwi.c
drivers/scsi/ppa.c
drivers/scsi/qedf/qedf_io.c
drivers/scsi/qedf/qedf_main.c
drivers/scsi/qla2xxx/qla_dfs.c
drivers/scsi/qla2xxx/qla_inline.h
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_nvme.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/spi/spi-imx.c
drivers/spi/spi-intel-pci.c
drivers/spi/spi-nxp-fspi.c
drivers/spi/spi-stm32.c
drivers/spi/spi-zynqmp-gqspi.c
drivers/target/target_core_configfs.c
drivers/target/target_core_transport.c
drivers/tee/amdtee/core.c
drivers/thermal/thermal_core.c
drivers/thermal/thermal_of.c
drivers/thermal/thermal_sysfs.c
drivers/thermal/ti-soc-thermal/ti-thermal-common.c
drivers/ufs/core/ufshcd.c
drivers/usb/typec/ucsi/debugfs.c
drivers/video/console/Kconfig
drivers/video/fbdev/Kconfig
drivers/video/fbdev/core/Kconfig
drivers/w1/masters/ds2482.c
drivers/xen/events/events_base.c
drivers/xen/platform-pci.c
fs/btrfs/Kconfig
fs/btrfs/block-group.c
fs/btrfs/delayed-inode.c
fs/btrfs/disk-io.c
fs/btrfs/extent_io.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/locking.h
fs/btrfs/ordered-data.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/btrfs/verity.c
fs/buffer.c
fs/efivarfs/super.c
fs/ext4/mballoc.c
fs/ext4/namei.c
fs/ext4/super.c
fs/gfs2/glock.c
fs/gfs2/glops.c
fs/gfs2/quota.h
fs/inode.c
fs/iomap/buffered-io.c
fs/jbd2/commit.c
fs/jbd2/journal.c
fs/jbd2/transaction.c
fs/netfs/buffered_read.c
fs/nfs/direct.c
fs/nfs/flexfilelayout/flexfilelayout.c
fs/nfs/nfs4client.c
fs/nfs/nfs4proc.c
fs/nfs/write.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfssvc.c
fs/overlayfs/copy_up.c
fs/overlayfs/file.c
fs/proc/internal.h
fs/proc/task_nommu.c
fs/smb/client/cached_dir.c
fs/smb/client/cifsglob.h
fs/smb/client/cifsproto.h
fs/smb/client/connect.c
fs/smb/client/inode.c
fs/smb/client/misc.c
fs/smb/client/smb2inode.c
fs/smb/client/smb2maperror.c
fs/smb/client/smb2ops.c
fs/smb/client/smb2pdu.c
fs/smb/client/smbdirect.c
fs/smb/client/trace.h
fs/smb/client/transport.c
fs/smb/server/smb2pdu.c
fs/smb/server/smbacl.c
fs/stat.c
fs/tracefs/event_inode.c
fs/tracefs/inode.c
fs/tracefs/internal.h
fs/xfs/Kconfig
fs/xfs/libxfs/xfs_log_recover.h
fs/xfs/libxfs/xfs_sb.c
fs/xfs/libxfs/xfs_trans_inode.c
fs/xfs/scrub/scrub.c
fs/xfs/scrub/stats.c
fs/xfs/xfs_attr_inactive.c
fs/xfs/xfs_attr_item.c
fs/xfs/xfs_bmap_item.c
fs/xfs/xfs_export.c
fs/xfs/xfs_extfree_item.c
fs/xfs/xfs_fsmap.c
fs/xfs/xfs_icache.c
fs/xfs/xfs_icache.h
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_iops.c
fs/xfs/xfs_itable.c
fs/xfs/xfs_log.c
fs/xfs/xfs_log_cil.c
fs/xfs/xfs_log_priv.h
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_mount.h
fs/xfs/xfs_qm.c
fs/xfs/xfs_refcount_item.c
fs/xfs/xfs_rmap_item.c
fs/xfs/xfs_super.c
fs/xfs/xfs_trace.h
fs/xfs/xfs_xattr.c
include/drm/drm_exec.h
include/drm/drm_kunit_helpers.h
include/linux/aer.h
include/linux/arm-smccc.h
include/linux/atomic/atomic-arch-fallback.h
include/linux/btf_ids.h
include/linux/buffer_head.h
include/linux/cpuhotplug.h
include/linux/export-internal.h
include/linux/fs.h
include/linux/i2c.h
include/linux/if_team.h
include/linux/instruction_pointer.h
include/linux/kasan.h
include/linux/libata.h
include/linux/memcontrol.h
include/linux/nfs_fs_sb.h
include/linux/nfs_page.h
include/linux/nvme-fc-driver.h
include/linux/resume_user_mode.h
include/linux/seqlock.h
include/linux/sunrpc/xdr.h
include/linux/thermal.h
include/linux/trace_events.h
include/net/ipv6.h
include/net/netfilter/nf_tables.h
include/trace/events/xen.h
include/uapi/linux/bpf.h
include/uapi/linux/stddef.h
include/xen/arm/hypervisor.h
include/xen/events.h
io_uring/net.c
kernel/bpf/btf.c
kernel/bpf/cgroup.c
kernel/bpf/memalloc.c
kernel/bpf/offload.c
kernel/bpf/queue_stack_maps.c
kernel/panic.c
kernel/pid.c
kernel/power/hibernate.c
kernel/power/power.h
kernel/power/swap.c
kernel/sched/core.c
kernel/sched/fair.c
kernel/sched/idle.c
kernel/task_work.c
kernel/trace/bpf_trace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_events.c
kernel/trace/trace_events_inject.c
kernel/trace/trace_events_synth.c
lib/argv_split.c
lib/kunit/executor.c
lib/kunit/executor_test.c
lib/kunit/test.c
lib/scatterlist.c
mm/filemap.c
mm/kasan/kasan.h
mm/memcontrol.c
mm/mremap.c
mm/page_alloc.c
mm/shmem.c
net/ax25/Kconfig
net/bridge/br_forward.c
net/bridge/br_input.c
net/core/dev.c
net/core/flow_dissector.c
net/dccp/ipv4.c
net/dccp/ipv6.c
net/handshake/handshake-test.c
net/hsr/hsr_forward.c
net/hsr/hsr_framereg.c
net/hsr/hsr_main.h
net/ipv4/devinet.c
net/ipv4/inet_hashtables.c
net/ipv4/route.c
net/kcm/kcmsock.c
net/mptcp/options.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/ncsi/ncsi-aen.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/nf_conntrack_bpf.c
net/netfilter/nf_conntrack_extend.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_set_hash.c
net/netfilter/nft_set_pipapo.c
net/netfilter/nft_set_rbtree.c
net/rds/rdma_transport.c
net/smc/smc_core.c
net/smc/smc_stats.h
net/sunrpc/clnt.c
net/tls/tls_sw.c
scripts/Makefile.modinst
scripts/atomic/gen-atomic-fallback.sh
scripts/gdb/linux/symbols.py
scripts/mod/modpost.c
scripts/package/install-extmod-build
security/selinux/hooks.c
sound/core/init.c
sound/core/rawmidi.c
sound/core/seq/seq_midi.c
sound/core/seq/seq_ump_client.c
sound/core/seq/seq_ump_convert.c
sound/firewire/bebob/bebob_midi.c
sound/firewire/dice/dice-midi.c
sound/firewire/digi00x/digi00x-midi.c
sound/firewire/fireface/ff-midi.c
sound/firewire/fireworks/fireworks.c
sound/firewire/fireworks/fireworks_midi.c
sound/firewire/motu/motu-midi.c
sound/firewire/oxfw/oxfw-midi.c
sound/firewire/oxfw/oxfw.c
sound/firewire/tascam/tascam-midi.c
sound/hda/intel-sdw-acpi.c
sound/isa/ad1848/ad1848.c
sound/isa/cs423x/cs4231.c
sound/isa/cs423x/cs4236.c
sound/isa/es1688/es1688.c
sound/isa/opti9xx/miro.c
sound/isa/opti9xx/opti92x-ad1848.c
sound/isa/sscape.c
sound/pci/cmipci.c
sound/pci/hda/cs35l56_hda.c
sound/pci/hda/cs35l56_hda_i2c.c
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/pci/riptide/riptide.c
sound/soc/amd/yc/acp6x-mach.c
sound/soc/codecs/aw88395/aw88395_lib.c
sound/soc/codecs/cs35l56-i2c.c
sound/soc/codecs/cs35l56.c
sound/soc/codecs/cs42l42-sdw.c
sound/soc/codecs/cs42l42.c
sound/soc/codecs/cs42l42.h
sound/soc/codecs/cs42l43.c
sound/soc/codecs/rt5640.c
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm_adsp.c
sound/soc/fsl/imx-audmix.c
sound/soc/fsl/imx-pcm-rpmsg.c
sound/soc/fsl/imx-rpmsg.c
sound/soc/intel/avs/boards/hdaudio.c
sound/soc/meson/axg-spdifin.c
sound/soc/sh/rcar/core.c
sound/soc/soc-pcm.c
sound/soc/soc-utils.c
sound/soc/sof/core.c
sound/soc/sof/intel/mtl.c
sound/soc/sof/intel/mtl.h
sound/soc/sof/ipc4-topology.c
sound/soc/sof/sof-audio.c
sound/soc/tegra/tegra_audio_graph_card.c
sound/usb/caiaq/device.c
sound/usb/mixer.c
sound/usb/mixer_scarlett_gen2.c
sound/xen/xen_snd_front_cfg.c
tools/include/linux/btf_ids.h
tools/include/linux/mm.h
tools/include/linux/seq_file.h
tools/include/uapi/linux/bpf.h
tools/objtool/check.c
tools/testing/memblock/internal.h
tools/testing/memblock/mmzone.c
tools/testing/memblock/tests/basic_api.c
tools/testing/memblock/tests/common.h
tools/testing/selftests/alsa/conf.c
tools/testing/selftests/alsa/mixer-test.c
tools/testing/selftests/alsa/pcm-test.c
tools/testing/selftests/alsa/test-pcmtest-driver.c
tools/testing/selftests/bpf/DENYLIST.aarch64
tools/testing/selftests/bpf/config
tools/testing/selftests/bpf/config.x86_64
tools/testing/selftests/bpf/prog_tests/empty_skb.c
tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
tools/testing/selftests/bpf/prog_tests/test_bpf_ma.c [new file with mode: 0644]
tools/testing/selftests/bpf/prog_tests/xdp_dev_bound_only.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/kprobe_multi_override.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/test_bpf_ma.c [new file with mode: 0644]
tools/testing/selftests/bpf/test_verifier.c
tools/testing/selftests/fchmodat2/Makefile
tools/testing/selftests/ftrace/ftracetest
tools/testing/selftests/ftrace/test.d/instances/instance-event.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-dynstring.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc
tools/testing/selftests/kselftest/runner.sh
tools/testing/selftests/kselftest_deps.sh
tools/testing/selftests/kvm/lib/test_util.c
tools/testing/selftests/kvm/riscv/get-reg-list.c
tools/testing/selftests/lib.mk
tools/testing/selftests/net/bind_bhash.sh
tools/testing/selftests/net/bind_wildcard.c
tools/testing/selftests/net/hsr/hsr_ping.sh
tools/testing/selftests/net/tls.c
tools/testing/selftests/netfilter/.gitignore
tools/testing/selftests/netfilter/Makefile
tools/testing/selftests/netfilter/audit_logread.c [new file with mode: 0644]
tools/testing/selftests/netfilter/config
tools/testing/selftests/netfilter/nft_audit.sh [new file with mode: 0755]
tools/testing/selftests/openat2/Makefile
tools/testing/selftests/proc/proc-empty-vm.c
tools/testing/selftests/user_events/abi_test.c
tools/testing/selftests/user_events/config [new file with mode: 0644]
tools/testing/selftests/user_events/dyn_test.c
tools/testing/selftests/user_events/ftrace_test.c
tools/testing/selftests/user_events/perf_test.c
tools/testing/selftests/user_events/user_events_selftests.h [new file with mode: 0644]

index 4e4625f2455fe92552365fc1c088d497bdef5a55..de6d8a4790e2b6cd06f69fe5ebe72eb69c23cb3d 100644 (file)
@@ -175,6 +175,8 @@ infrastructure:
      +------------------------------+---------+---------+
      | Name                         |  bits   | visible |
      +------------------------------+---------+---------+
+     | SME                          | [27-24] |    y    |
+     +------------------------------+---------+---------+
      | MTE                          | [11-8]  |    y    |
      +------------------------------+---------+---------+
      | SSBS                         | [7-4]   |    y    |
@@ -288,8 +290,18 @@ infrastructure:
      +------------------------------+---------+---------+
      | Name                         |  bits   | visible |
      +------------------------------+---------+---------+
+     | CSSC                         | [55-52] |    y    |
+     +------------------------------+---------+---------+
+     | RPRFM                        | [51-48] |    y    |
+     +------------------------------+---------+---------+
+     | BC                           | [23-20] |    y    |
+     +------------------------------+---------+---------+
      | MOPS                         | [19-16] |    y    |
      +------------------------------+---------+---------+
+     | APA3                         | [15-12] |    y    |
+     +------------------------------+---------+---------+
+     | GPA3                         | [11-8]  |    y    |
+     +------------------------------+---------+---------+
      | RPRES                        | [7-4]   |    y    |
      +------------------------------+---------+---------+
      | WFXT                         | [3-0]   |    y    |
index 8c8addb4194c93446936e60af3b9e7c744e75575..76ff9d7398fda74afd576f6f6734688cb111eb20 100644 (file)
@@ -305,6 +305,9 @@ HWCAP2_SMEF16F16
 HWCAP2_MOPS
     Functionality implied by ID_AA64ISAR2_EL1.MOPS == 0b0001.
 
+HWCAP2_HBC
+    Functionality implied by ID_AA64ISAR2_EL1.BC == 0b0001.
+
 4. Unused AT_HWCAP bits
 -----------------------
 
index 49135d451ced9a0b9fa5c54a7d52d82880521b32..8c568cfc2107984092f4d82c2076a3bed0c05c4f 100644 (file)
@@ -381,9 +381,9 @@ Documentation of LoongArch ISA:
 
 Documentation of LoongArch ELF psABI:
 
-  https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-CN.pdf (in Chinese)
+  https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.01-CN.pdf (in Chinese)
 
-  https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-EN.pdf (in English)
+  https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.01-EN.pdf (in English)
 
 Linux kernel repository of Loongson and LoongArch:
 
index 992eddb0e11b8751c125acc45fdd7fbba2cf3962..a81db8f54d689300a49ff78cb06ba783dcdad21d 100644 (file)
@@ -37,7 +37,6 @@ For more information please refer to the documentation site or wiki
 
   https://btrfs.readthedocs.io
 
-  https://btrfs.wiki.kernel.org
 
 that maintains information about administration tasks, frequently asked
 questions, use cases, mount options, comprehensible changelogs, features,
index f060cfb1445a38a6e0d81c68e5184815976b7fed..605e72c6c8771dbdd8085d89874b2a8bb1008005 100644 (file)
@@ -7,9 +7,9 @@ AX.25
 To use the amateur radio protocols within Linux you will need to get a
 suitable copy of the AX.25 Utilities. More detailed information about
 AX.25, NET/ROM and ROSE, associated programs and utilities can be
-found on http://www.linux-ax25.org.
+found on https://linux-ax25.in-berlin.de.
 
-There is an active mailing list for discussing Linux amateur radio matters
+There is a mailing list for discussing Linux amateur radio matters
 called linux-hams@vger.kernel.org. To subscribe to it, send a message to
 majordomo@vger.kernel.org with the words "subscribe linux-hams" in the body
 of the message, the subject field is ignored.  You don't need to be
index cb686238f21d1de3bb3483d629237779b240120c..ac7c52f130c9b30978267fdd9d92994f01878260 100644 (file)
@@ -251,6 +251,7 @@ an involved disclosed party. The current ambassadors list:
   IBM Z                Christian Borntraeger <borntraeger@de.ibm.com>
   Intel                Tony Luck <tony.luck@intel.com>
   Qualcomm     Trilok Soni <tsoni@codeaurora.org>
+  RISC-V       Palmer Dabbelt <palmer@dabbelt.com>
   Samsung      Javier González <javier.gonz@samsung.com>
 
   Microsoft    James Morris <jamorris@linux.microsoft.com>
index 45987f256b976312644e94522f5565fbf062e255..086487ca7ab11905a8374437d31f12c29f84a402 100644 (file)
@@ -74,8 +74,8 @@ topology based on those information.  When the device is older and
 doesn't respond to the new UMP inquiries, the driver falls back and
 builds the topology based on Group Terminal Block (GTB) information
 from the USB descriptor.  Some device might be screwed up by the
-unexpected UMP command; in such a case, pass `midi2_probe=0` option to
-snd-usb-audio driver for skipping the UMP v1.1 inquiries.
+unexpected UMP command; in such a case, pass `midi2_ump_probe=0`
+option to snd-usb-audio driver for skipping the UMP v1.1 inquiries.
 
 When the MIDI 2.0 device is probed, the kernel creates a rawmidi
 device for each UMP Endpoint of the device.  Its device name is
index cba04befc9509f8942eb1e2b1aadc2f80fe17034..59d6bf33050cb831236321d91eab7bbf313655ea 100644 (file)
@@ -344,9 +344,9 @@ LoongArch指令集架构的文档:
 
 LoongArch的ELF psABI文档:
 
-  https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-CN.pdf (中文版)
+  https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.01-CN.pdf (中文版)
 
-  https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-EN.pdf (英文版)
+  https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.01-EN.pdf (英文版)
 
 Loongson与LoongArch的Linux内核源码仓库:
 
index 90f13281d29708439ba448d26308109a3cfd747b..b6a1b7a868755bab33ba2b42fa76e12418cefab5 100644 (file)
@@ -1662,7 +1662,7 @@ F:        arch/arm*/include/asm/perf_event.h
 F:     arch/arm*/kernel/hw_breakpoint.c
 F:     arch/arm*/kernel/perf_*
 F:     drivers/perf/
-F:     include/linux/perf/arm_pmu.h
+F:     include/linux/perf/arm_pmu*.h
 
 ARM PORT
 M:     Russell King <linux@armlinux.org.uk>
@@ -1855,7 +1855,7 @@ F:        Documentation/devicetree/bindings/phy/amlogic*
 F:     arch/arm/boot/dts/amlogic/
 F:     arch/arm/mach-meson/
 F:     arch/arm64/boot/dts/amlogic/
-F:     drivers/genpd/amlogic/
+F:     drivers/pmdomain/amlogic/
 F:     drivers/mmc/host/meson*
 F:     drivers/phy/amlogic/
 F:     drivers/pinctrl/meson/
@@ -1918,7 +1918,7 @@ F:        drivers/bluetooth/hci_bcm4377.c
 F:     drivers/clk/clk-apple-nco.c
 F:     drivers/cpufreq/apple-soc-cpufreq.c
 F:     drivers/dma/apple-admac.c
-F:     drivers/genpd/apple/
+F:     drivers/pmdomain/apple/
 F:     drivers/i2c/busses/i2c-pasemi-core.c
 F:     drivers/i2c/busses/i2c-pasemi-platform.c
 F:     drivers/iommu/apple-dart.c
@@ -2327,7 +2327,7 @@ F:        drivers/rtc/rtc-mt7622.c
 
 ARM/Mediatek SoC support
 M:     Matthias Brugger <matthias.bgg@gmail.com>
-R:     AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+M:     AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
 L:     linux-kernel@vger.kernel.org
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-mediatek@lists.infradead.org (moderated for non-subscribers)
@@ -2435,7 +2435,7 @@ F:        arch/arm/mach-ux500/
 F:     drivers/clk/clk-nomadik.c
 F:     drivers/clocksource/clksrc-dbx500-prcmu.c
 F:     drivers/dma/ste_dma40*
-F:     drivers/genpd/st/ste-ux500-pm-domain.c
+F:     drivers/pmdomain/st/ste-ux500-pm-domain.c
 F:     drivers/hwspinlock/u8500_hsem.c
 F:     drivers/i2c/busses/i2c-nomadik.c
 F:     drivers/iio/adc/ab8500-gpadc.c
@@ -2598,7 +2598,7 @@ F:        arch/arm/include/debug/renesas-scif.S
 F:     arch/arm/mach-shmobile/
 F:     arch/arm64/boot/dts/renesas/
 F:     arch/riscv/boot/dts/renesas/
-F:     drivers/genpd/renesas/
+F:     drivers/pmdomain/renesas/
 F:     drivers/soc/renesas/
 F:     include/linux/soc/renesas/
 K:     \brenesas,
@@ -3344,7 +3344,7 @@ AX.25 NETWORK LAYER
 M:     Ralf Baechle <ralf@linux-mips.org>
 L:     linux-hams@vger.kernel.org
 S:     Maintained
-W:     http://www.linux-ax25.org/
+W:     https://linux-ax25.in-berlin.de
 F:     include/net/ax25.h
 F:     include/uapi/linux/ax25.h
 F:     net/ax25/
@@ -4026,7 +4026,7 @@ F:        arch/mips/kernel/*bmips*
 F:     drivers/irqchip/irq-bcm63*
 F:     drivers/irqchip/irq-bcm7*
 F:     drivers/irqchip/irq-brcmstb*
-F:     drivers/genpd/bcm/bcm63xx-power.c
+F:     drivers/pmdomain/bcm/bcm63xx-power.c
 F:     include/linux/bcm963xx_nvram.h
 F:     include/linux/bcm963xx_tag.h
 
@@ -4248,7 +4248,7 @@ R:        Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
 L:     linux-pm@vger.kernel.org
 S:     Maintained
 T:     git https://github.com/broadcom/stblinux.git
-F:     drivers/genpd/bcm/bcm-pmb.c
+F:     drivers/pmdomain/bcm/bcm-pmb.c
 F:     include/dt-bindings/soc/bcm-pmb.h
 
 BROADCOM SPECIFIC AMBA DRIVER (BCMA)
@@ -4378,7 +4378,6 @@ M:        David Sterba <dsterba@suse.com>
 L:     linux-btrfs@vger.kernel.org
 S:     Maintained
 W:     https://btrfs.readthedocs.io
-W:     https://btrfs.wiki.kernel.org/
 Q:     https://patchwork.kernel.org/project/linux-btrfs/list/
 C:     irc://irc.libera.chat/btrfs
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git
@@ -6646,7 +6645,6 @@ F:        Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml
 F:     drivers/gpu/drm/panel/panel-novatek-nt36672a.c
 
 DRM DRIVER FOR NVIDIA GEFORCE/QUADRO GPUS
-M:     Ben Skeggs <bskeggs@redhat.com>
 M:     Karol Herbst <kherbst@redhat.com>
 M:     Lyude Paul <lyude@redhat.com>
 L:     dri-devel@lists.freedesktop.org
@@ -8729,7 +8727,7 @@ M:        Ulf Hansson <ulf.hansson@linaro.org>
 L:     linux-pm@vger.kernel.org
 S:     Supported
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm.git
-F:     drivers/genpd/
+F:     drivers/pmdomain/
 
 GENERIC RESISTIVE TOUCHSCREEN ADC DRIVER
 M:     Eugen Hristev <eugen.hristev@microchip.com>
@@ -8875,7 +8873,7 @@ F:        drivers/gpio/gpio-mockup.c
 F:     tools/testing/selftests/gpio/
 
 GPIO REGMAP
-R:     Michael Walle <michael@walle.cc>
+M:     Michael Walle <michael@walle.cc>
 S:     Maintained
 F:     drivers/gpio/gpio-regmap.c
 F:     include/linux/gpio/regmap.h
@@ -13617,6 +13615,7 @@ F:      drivers/net/ethernet/mellanox/mlxfw/
 
 MELLANOX HARDWARE PLATFORM SUPPORT
 M:     Hans de Goede <hdegoede@redhat.com>
+M:     Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
 M:     Mark Gross <markgross@kernel.org>
 M:     Vadim Pasternak <vadimp@nvidia.com>
 L:     platform-driver-x86@vger.kernel.org
@@ -14211,6 +14210,7 @@ F:      drivers/platform/surface/surface_gpe.c
 
 MICROSOFT SURFACE HARDWARE PLATFORM SUPPORT
 M:     Hans de Goede <hdegoede@redhat.com>
+M:     Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
 M:     Mark Gross <markgross@kernel.org>
 M:     Maximilian Luz <luzmaximilian@gmail.com>
 L:     platform-driver-x86@vger.kernel.org
@@ -14757,7 +14757,7 @@ NETROM NETWORK LAYER
 M:     Ralf Baechle <ralf@linux-mips.org>
 L:     linux-hams@vger.kernel.org
 S:     Maintained
-W:     http://www.linux-ax25.org/
+W:     https://linux-ax25.in-berlin.de
 F:     include/net/netrom.h
 F:     include/uapi/linux/netrom.h
 F:     net/netrom/
@@ -17680,7 +17680,7 @@ L:      linux-pm@vger.kernel.org
 L:     linux-arm-msm@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/power/avs/qcom,cpr.yaml
-F:     drivers/genpd/qcom/cpr.c
+F:     drivers/pmdomain/qcom/cpr.c
 
 QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096
 M:     Ilia Lin <ilia.lin@kernel.org>
@@ -18608,7 +18608,7 @@ ROSE NETWORK LAYER
 M:     Ralf Baechle <ralf@linux-mips.org>
 L:     linux-hams@vger.kernel.org
 S:     Maintained
-W:     http://www.linux-ax25.org/
+W:     https://linux-ax25.in-berlin.de
 F:     include/net/rose.h
 F:     include/uapi/linux/rose.h
 F:     net/rose/
@@ -20514,7 +20514,7 @@ STARFIVE JH71XX PMU CONTROLLER DRIVER
 M:     Walker Chen <walker.chen@starfivetech.com>
 S:     Supported
 F:     Documentation/devicetree/bindings/power/starfive*
-F:     drivers/genpd/starfive/jh71xx-pmu.c
+F:     drivers/pmdomain/starfive/jh71xx-pmu.c
 F:     include/dt-bindings/power/starfive,jh7110-pmu.h
 
 STARFIVE SOC DRIVERS
@@ -21339,7 +21339,7 @@ F:      drivers/irqchip/irq-ti-sci-inta.c
 F:     drivers/irqchip/irq-ti-sci-intr.c
 F:     drivers/reset/reset-ti-sci.c
 F:     drivers/soc/ti/ti_sci_inta_msi.c
-F:     drivers/genpd/ti/ti_sci_pm_domains.c
+F:     drivers/pmdomain/ti/ti_sci_pm_domains.c
 F:     include/dt-bindings/soc/ti,sci_pm_domain.h
 F:     include/linux/soc/ti/ti_sci_inta_msi.h
 F:     include/linux/soc/ti/ti_sci_protocol.h
@@ -21581,7 +21581,7 @@ L:      linux-kernel@vger.kernel.org
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
-F:     drivers/genpd/ti/omap_prm.c
+F:     drivers/pmdomain/ti/omap_prm.c
 F:     drivers/soc/ti/*
 
 TI LM49xxx FAMILY ASoC CODEC DRIVERS
@@ -23424,9 +23424,11 @@ F:     drivers/platform/x86/x86-android-tablets/
 
 X86 PLATFORM DRIVERS
 M:     Hans de Goede <hdegoede@redhat.com>
+M:     Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
 M:     Mark Gross <markgross@kernel.org>
 L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
+Q:     https://patchwork.kernel.org/project/platform-driver-x86/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git
 F:     drivers/platform/olpc/
 F:     drivers/platform/x86/
index ceb23eed4dce2b0d826e0ac21c51b659392f80ed..3de08c780c7459818ee5148e531d81f0e9a9c12c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 6
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc3
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
index 7d59765aef220b429afdf7a8d3a2a6ec0923c0b2..c392e18f1e43178fd00a177033baba203e25e931 100644 (file)
@@ -207,7 +207,7 @@ static void xen_power_off(void)
 
 static irqreturn_t xen_arm_callback(int irq, void *arg)
 {
-       xen_hvm_evtchn_do_upcall();
+       xen_evtchn_do_upcall();
        return IRQ_HANDLED;
 }
 
index 36ef2dbe8add484ea9d3ba0fbb294376d77a9215..3ee9266fa8e985cedcd4177f04dfdff8a4b689f4 100644 (file)
                status = "disabled";
        };
 
-       sata_phy: t-phy@1a243000 {
+       sata_phy: t-phy {
                compatible = "mediatek,mt7622-tphy",
                             "mediatek,generic-tphy-v1";
                #address-cells = <2>;
index 68539ea788dfcce5e52cb996693de7766607e05e..24eda00e320d3a8873a702966f8b674b737425a3 100644 (file)
                        };
                };
 
-               pcie_phy: t-phy@11c00000 {
+               pcie_phy: t-phy {
                        compatible = "mediatek,mt7986-tphy",
                                     "mediatek,generic-tphy-v2";
                        #address-cells = <2>;
index b2485ddfd33bbdae83b1a37d2d0edd60a7570d18..5d635085fe3fd0cc6534dd0bd045bbf8642de59b 100644 (file)
@@ -48,7 +48,7 @@
 
        memory@40000000 {
                device_type = "memory";
-               reg = <0 0x40000000 0 0x80000000>;
+               reg = <0 0x40000000 0x2 0x00000000>;
        };
 
        reserved-memory {
                #size-cells = <2>;
                ranges;
 
-               /* 2 MiB reserved for ARM Trusted Firmware (BL31) */
-               bl31_secmon_reserved: secmon@54600000 {
-                       no-map;
-                       reg = <0 0x54600000 0x0 0x200000>;
-               };
-
-               /* 12 MiB reserved for OP-TEE (BL32)
+               /*
+                * 12 MiB reserved for OP-TEE (BL32)
                 * +-----------------------+ 0x43e0_0000
                 * |      SHMEM 2MiB       |
                 * +-----------------------+ 0x43c0_0000
                        no-map;
                        reg = <0 0x43200000 0 0x00c00000>;
                };
+
+               scp_mem: memory@50000000 {
+                       compatible = "shared-dma-pool";
+                       reg = <0 0x50000000 0 0x2900000>;
+                       no-map;
+               };
+
+               vpu_mem: memory@53000000 {
+                       compatible = "shared-dma-pool";
+                       reg = <0 0x53000000 0 0x1400000>; /* 20 MB */
+               };
+
+               /* 2 MiB reserved for ARM Trusted Firmware (BL31) */
+               bl31_secmon_mem: memory@54600000 {
+                       no-map;
+                       reg = <0 0x54600000 0x0 0x200000>;
+               };
+
+               snd_dma_mem: memory@60000000 {
+                       compatible = "shared-dma-pool";
+                       reg = <0 0x60000000 0 0x1100000>;
+                       no-map;
+               };
+
+               apu_mem: memory@62000000 {
+                       compatible = "shared-dma-pool";
+                       reg = <0 0x62000000 0 0x1400000>; /* 20 MB */
+               };
        };
 };
 
index 4dbbf8fdab75857d7a9f889c3222900331c81174..43011bc41da770292799b9e492f92bffb15532e7 100644 (file)
                interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH 0>;
                cpus = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>,
                       <&cpu4>, <&cpu5>, <&cpu6>, <&cpu7>;
+               status = "fail";
        };
 
        dmic_codec: dmic-codec {
index 96e50227f940ecbde381ccc422d9d8c1433e5e2c..5bba393760557d0b390ff39927de19d861af006d 100644 (file)
@@ -663,7 +663,7 @@ static inline bool supports_clearbhb(int scope)
                isar2 = read_sanitised_ftr_reg(SYS_ID_AA64ISAR2_EL1);
 
        return cpuid_feature_extract_unsigned_field(isar2,
-                                                   ID_AA64ISAR2_EL1_BC_SHIFT);
+                                                   ID_AA64ISAR2_EL1_CLRBHB_SHIFT);
 }
 
 const struct cpumask *system_32bit_el0_cpumask(void);
index b7238c72a04cfaee4cdd4510e408e5f0a6c4df6f..66efd67ea7e8d6dd98dc6088a6004fdb646df2a3 100644 (file)
@@ -118,7 +118,7 @@ void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu);
 
 u64 __guest_enter(struct kvm_vcpu *vcpu);
 
-bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt);
+bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt, u32 func_id);
 
 #ifdef __KVM_NVHE_HYPERVISOR__
 void __noreturn __hyp_do_panic(struct kvm_cpu_context *host_ctxt, u64 spsr,
index b018ae12ff5f2cc288545fb43f51ebbca7624bca..444a73c2e63858cea758fb89c5d65b786bc6f5f3 100644 (file)
@@ -222,7 +222,8 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
 static const struct arm64_ftr_bits ftr_id_aa64isar2[] = {
        ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_CSSC_SHIFT, 4, 0),
        ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_RPRFM_SHIFT, 4, 0),
-       ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, ID_AA64ISAR2_EL1_BC_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_CLRBHB_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_BC_SHIFT, 4, 0),
        ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_MOPS_SHIFT, 4, 0),
        ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH),
                       FTR_STRICT, FTR_EXACT, ID_AA64ISAR2_EL1_APA3_SHIFT, 4, 0),
index 1becb10ecd8057d49dac1730409bfb10077cd1e0..d9fd5e6c7d3cca73c1f687e64d7848cceae92f98 100644 (file)
@@ -12,6 +12,6 @@
 #define FFA_MAX_FUNC_NUM 0x7F
 
 int hyp_ffa_init(void *pages);
-bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt);
+bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id);
 
 #endif /* __KVM_HYP_FFA_H */
index ab4f5d160c58f9969f4820a479dbf3d119b2d617..6e4dba9eadef522fe7c4ccc93e362d405aa259c1 100644 (file)
@@ -634,9 +634,8 @@ out_handled:
        return true;
 }
 
-bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt)
+bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
 {
-       DECLARE_REG(u64, func_id, host_ctxt, 0);
        struct arm_smccc_res res;
 
        /*
index 90fade1b032e4bc614861ebd49e8738042768d65..1cc06e6797bda378a59b072de8c6f9a1612f6893 100644 (file)
@@ -57,6 +57,7 @@ __do_hyp_init:
        cmp     x0, #HVC_STUB_HCALL_NR
        b.lo    __kvm_handle_stub_hvc
 
+       bic     x0, x0, #ARM_SMCCC_CALL_HINTS
        mov     x3, #KVM_HOST_SMCCC_FUNC(__kvm_hyp_init)
        cmp     x0, x3
        b.eq    1f
index 857d9bc04fd48a58bedaa8ab457088bfd7817600..2385fd03ed87c6c0450a1c2dbe830e95ce235ecc 100644 (file)
@@ -368,6 +368,7 @@ static void handle_host_hcall(struct kvm_cpu_context *host_ctxt)
        if (static_branch_unlikely(&kvm_protected_mode_initialized))
                hcall_min = __KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize;
 
+       id &= ~ARM_SMCCC_CALL_HINTS;
        id -= KVM_HOST_SMCCC_ID(0);
 
        if (unlikely(id < hcall_min || id >= ARRAY_SIZE(host_hcall)))
@@ -392,11 +393,14 @@ static void default_host_smc_handler(struct kvm_cpu_context *host_ctxt)
 
 static void handle_host_smc(struct kvm_cpu_context *host_ctxt)
 {
+       DECLARE_REG(u64, func_id, host_ctxt, 0);
        bool handled;
 
-       handled = kvm_host_psci_handler(host_ctxt);
+       func_id &= ~ARM_SMCCC_CALL_HINTS;
+
+       handled = kvm_host_psci_handler(host_ctxt, func_id);
        if (!handled)
-               handled = kvm_host_ffa_handler(host_ctxt);
+               handled = kvm_host_ffa_handler(host_ctxt, func_id);
        if (!handled)
                default_host_smc_handler(host_ctxt);
 
index 24543d2a34905c66cfe39b68831b5e242359a5eb..d57bcb6ab94d25b9998bbabd5cd0cdb2fd27e794 100644 (file)
@@ -273,9 +273,8 @@ static unsigned long psci_1_0_handler(u64 func_id, struct kvm_cpu_context *host_
        }
 }
 
-bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt)
+bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
 {
-       DECLARE_REG(u64, func_id, host_ctxt, 0);
        unsigned long ret;
 
        switch (kvm_host_psci_config.version) {
index 587a104f66c371df5aabc8f38aecf624e33d65af..482280fe22d7c59d2539b9f0e758cfc95afad0ff 100644 (file)
@@ -652,6 +652,9 @@ int hyp_alloc_private_va_range(size_t size, unsigned long *haddr)
 
        mutex_unlock(&kvm_hyp_pgd_mutex);
 
+       if (!ret)
+               *haddr = base;
+
        return ret;
 }
 
index 2517ef7c21cfc3532e86bce11d9ca7e01e902607..76ce150e7347e56e2f497e905c02dc28733e68e3 100644 (file)
@@ -1347,7 +1347,11 @@ UnsignedEnum     51:48   RPRFM
        0b0000  NI
        0b0001  IMP
 EndEnum
-Res0   47:28
+Res0   47:32
+UnsignedEnum   31:28   CLRBHB
+       0b0000  NI
+       0b0001  IMP
+EndEnum
 UnsignedEnum   27:24   PAC_frac
        0b0000  NI
        0b0001  IMP
index 15f6cfddcc080b47693f2b6212d4ca5fab6bf3e0..41e8fe55cd9845f2c0e285e5db888915705d9b0d 100644 (file)
@@ -907,3 +907,7 @@ EXPORT_SYMBOL(acpi_unregister_ioapic);
  * TBD when IA64 starts to support suspend...
  */
 int acpi_suspend_lowlevel(void) { return 0; }
+
+void acpi_proc_quirk_mwait_check(void)
+{
+}
index 5c9c03bdf91569154b9a449019e29b46049d5bef..b24437e28c6eda457b2be003b51ad3809600f7cc 100644 (file)
@@ -19,7 +19,7 @@
  */
 #ifndef __ASSEMBLY__
 #ifndef PHYS_OFFSET
-#define PHYS_OFFSET    _AC(0, UL)
+#define PHYS_OFFSET    _UL(0)
 #endif
 extern unsigned long vm_map_base;
 #endif /* __ASSEMBLY__ */
@@ -43,7 +43,7 @@ extern unsigned long vm_map_base;
  * Memory above this physical address will be considered highmem.
  */
 #ifndef HIGHMEM_START
-#define HIGHMEM_START          (_AC(1, UL) << _AC(DMW_PABITS, UL))
+#define HIGHMEM_START          (_UL(1) << _UL(DMW_PABITS))
 #endif
 
 #define TO_PHYS(x)             (               ((x) & TO_PHYS_MASK))
@@ -65,16 +65,16 @@ extern unsigned long vm_map_base;
 #define _ATYPE_
 #define _ATYPE32_
 #define _ATYPE64_
-#define _CONST64_(x)   x
 #else
 #define _ATYPE_                __PTRDIFF_TYPE__
 #define _ATYPE32_      int
 #define _ATYPE64_      __s64
+#endif
+
 #ifdef CONFIG_64BIT
-#define _CONST64_(x)   x ## UL
+#define _CONST64_(x)   _UL(x)
 #else
-#define _CONST64_(x)   x ## ULL
-#endif
+#define _CONST64_(x)   _ULL(x)
 #endif
 
 /*
diff --git a/arch/loongarch/include/asm/exception.h b/arch/loongarch/include/asm/exception.h
new file mode 100644 (file)
index 0000000..af74a3f
--- /dev/null
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_EXCEPTION_H
+#define __ASM_EXCEPTION_H
+
+#include <asm/ptrace.h>
+#include <linux/kprobes.h>
+
+void show_registers(struct pt_regs *regs);
+
+asmlinkage void cache_parity_error(void);
+asmlinkage void noinstr do_ade(struct pt_regs *regs);
+asmlinkage void noinstr do_ale(struct pt_regs *regs);
+asmlinkage void noinstr do_bce(struct pt_regs *regs);
+asmlinkage void noinstr do_bp(struct pt_regs *regs);
+asmlinkage void noinstr do_ri(struct pt_regs *regs);
+asmlinkage void noinstr do_fpu(struct pt_regs *regs);
+asmlinkage void noinstr do_fpe(struct pt_regs *regs, unsigned long fcsr);
+asmlinkage void noinstr do_lsx(struct pt_regs *regs);
+asmlinkage void noinstr do_lasx(struct pt_regs *regs);
+asmlinkage void noinstr do_lbt(struct pt_regs *regs);
+asmlinkage void noinstr do_watch(struct pt_regs *regs);
+asmlinkage void noinstr do_syscall(struct pt_regs *regs);
+asmlinkage void noinstr do_reserved(struct pt_regs *regs);
+asmlinkage void noinstr do_vint(struct pt_regs *regs, unsigned long sp);
+asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
+                               unsigned long write, unsigned long address);
+
+asmlinkage void handle_ade(void);
+asmlinkage void handle_ale(void);
+asmlinkage void handle_bce(void);
+asmlinkage void handle_sys(void);
+asmlinkage void handle_bp(void);
+asmlinkage void handle_ri(void);
+asmlinkage void handle_fpu(void);
+asmlinkage void handle_fpe(void);
+asmlinkage void handle_lsx(void);
+asmlinkage void handle_lasx(void);
+asmlinkage void handle_lbt(void);
+asmlinkage void handle_watch(void);
+asmlinkage void handle_reserved(void);
+asmlinkage void handle_vint(void);
+asmlinkage void noinstr handle_loongarch_irq(struct pt_regs *regs);
+
+#endif /* __ASM_EXCEPTION_H */
index deeff8158f45ce1df6bdb0c0169cd31ff8132240..cd6084f4e153feef9140ba198207b4a50fe0cfc2 100644 (file)
@@ -10,8 +10,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 
-#define __HAVE_ARCH_SHADOW_MAP
-
 #define KASAN_SHADOW_SCALE_SHIFT 3
 #define KASAN_SHADOW_OFFSET    _AC(CONFIG_KASAN_SHADOW_OFFSET, UL)
 
 extern bool kasan_early_stage;
 extern unsigned char kasan_early_shadow_page[PAGE_SIZE];
 
+#define kasan_mem_to_shadow kasan_mem_to_shadow
+void *kasan_mem_to_shadow(const void *addr);
+
+#define kasan_shadow_to_mem kasan_shadow_to_mem
+const void *kasan_shadow_to_mem(const void *shadow_addr);
+
 #define kasan_arch_is_ready kasan_arch_is_ready
 static __always_inline bool kasan_arch_is_ready(void)
 {
        return !kasan_early_stage;
 }
 
-static inline void *kasan_mem_to_shadow(const void *addr)
-{
-       if (!kasan_arch_is_ready()) {
-               return (void *)(kasan_early_shadow_page);
-       } else {
-               unsigned long maddr = (unsigned long)addr;
-               unsigned long xrange = (maddr >> XRANGE_SHIFT) & 0xffff;
-               unsigned long offset = 0;
-
-               maddr &= XRANGE_SHADOW_MASK;
-               switch (xrange) {
-               case XKPRANGE_CC_SEG:
-                       offset = XKPRANGE_CC_SHADOW_OFFSET;
-                       break;
-               case XKPRANGE_UC_SEG:
-                       offset = XKPRANGE_UC_SHADOW_OFFSET;
-                       break;
-               case XKVRANGE_VC_SEG:
-                       offset = XKVRANGE_VC_SHADOW_OFFSET;
-                       break;
-               default:
-                       WARN_ON(1);
-                       return NULL;
-               }
-
-               return (void *)((maddr >> KASAN_SHADOW_SCALE_SHIFT) + offset);
-       }
-}
-
-static inline const void *kasan_shadow_to_mem(const void *shadow_addr)
+#define addr_has_metadata addr_has_metadata
+static __always_inline bool addr_has_metadata(const void *addr)
 {
-       unsigned long addr = (unsigned long)shadow_addr;
-
-       if (unlikely(addr > KASAN_SHADOW_END) ||
-               unlikely(addr < KASAN_SHADOW_START)) {
-               WARN_ON(1);
-               return NULL;
-       }
-
-       if (addr >= XKVRANGE_VC_SHADOW_OFFSET)
-               return (void *)(((addr - XKVRANGE_VC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKVRANGE_VC_START);
-       else if (addr >= XKPRANGE_UC_SHADOW_OFFSET)
-               return (void *)(((addr - XKPRANGE_UC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKPRANGE_UC_START);
-       else if (addr >= XKPRANGE_CC_SHADOW_OFFSET)
-               return (void *)(((addr - XKPRANGE_CC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKPRANGE_CC_START);
-       else {
-               WARN_ON(1);
-               return NULL;
-       }
+       return (kasan_mem_to_shadow((void *)addr) != NULL);
 }
 
 void kasan_init(void);
index 66ecb480c894aa3f29843e711e374812fff3e658..f81e5f01d61905f5b8d7da4786ba512258381acd 100644 (file)
@@ -70,6 +70,7 @@ struct secondary_data {
 extern struct secondary_data cpuboot_data;
 
 extern asmlinkage void smpboot_entry(void);
+extern asmlinkage void start_secondary(void);
 
 extern void calculate_cpu_foreign_map(void);
 
index c56ea0b7544899e2b7ccf6aee30c8ae40fe350d0..4fcc168f07323154b4d7fc6712ab7a2298bb0d3e 100644 (file)
@@ -19,6 +19,10 @@ obj-$(CONFIG_CPU_HAS_LBT)    += lbt.o
 
 obj-$(CONFIG_ARCH_STRICT_ALIGN)        += unaligned.o
 
+CFLAGS_module.o                += $(call cc-option,-Wno-override-init,)
+CFLAGS_syscall.o       += $(call cc-option,-Wno-override-init,)
+CFLAGS_perf_event.o    += $(call cc-option,-Wno-override-init,)
+
 ifdef CONFIG_FUNCTION_TRACER
   ifndef CONFIG_DYNAMIC_FTRACE
     obj-y += mcount.o ftrace.o
index 9450e09073ebf7411e200a21a5a666c7dad092be..8e00a754e548943ae4dba5d330a1354426c713d1 100644 (file)
@@ -281,7 +281,6 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
        pr_info("SRAT: PXM %u -> CPU 0x%02x -> Node %u\n", pxm, pa->apic_id, node);
 }
 
-void __init acpi_numa_arch_fixup(void) {}
 #endif
 
 void __init arch_reserve_mem_area(acpi_physical_address addr, size_t size)
index 4a4107a6a9651535fc6cfb72f21cc1fb64f7eeed..aed901c57fb439493c560de777fbc86689f827ae 100644 (file)
@@ -50,7 +50,6 @@ void __init memblock_init(void)
        }
 
        memblock_set_current_limit(PFN_PHYS(max_low_pfn));
-       memblock_set_node(0, PHYS_ADDR_MAX, &memblock.memory, 0);
 
        /* Reserve the first 2MB */
        memblock_reserve(PHYS_OFFSET, 0x200000);
@@ -58,4 +57,7 @@ void __init memblock_init(void)
        /* Reserve the kernel text/data/bss */
        memblock_reserve(__pa_symbol(&_text),
                         __pa_symbol(&_end) - __pa_symbol(&_text));
+
+       memblock_set_node(0, PHYS_ADDR_MAX, &memblock.memory, 0);
+       memblock_set_node(0, PHYS_ADDR_MAX, &memblock.reserved, 0);
 }
index d4dbcda1c4b0a42a7d7de52fe9f457a22d4940cb..e2f30ff9afde825aea7f83bb529dc9e1cc5dd785 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/elf.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/moduleloader.h>
 #include <linux/ftrace.h>
 
 Elf_Addr module_emit_got_entry(struct module *mod, Elf_Shdr *sechdrs, Elf_Addr val)
index 3cb082e0c99298c44ebbf062a0e6d42be7073dc6..767d94cce0de07d74892733b339a55dd5e6ded0e 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
 #include <asm/elf.h>
+#include <asm/exec.h>
 #include <asm/fpu.h>
 #include <asm/lbt.h>
 #include <asm/io.h>
index d13252553a7c7d6f7916fda58f7fcdc1d9bae126..f49f6b053763d1e729b68b870b1b64ffe09d4504 100644 (file)
@@ -72,7 +72,6 @@ copy_word:
        LONG_ADDI       s5, s5, -1
        beqz            s5, process_entry
        b               copy_word
-       b               process_entry
 
 done:
        ibar            0
index 504fdfe852030f54ca66a00fdde05abd4d577907..4a3686d133494921d64853e6c94b061dfe262bc0 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/audit.h>
 #include <linux/cache.h>
 #include <linux/context_tracking.h>
+#include <linux/entry-common.h>
 #include <linux/irqflags.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -891,8 +892,8 @@ static unsigned long setup_extcontext(struct extctx_layout *extctx, unsigned lon
        return new_sp;
 }
 
-void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
-                         struct extctx_layout *extctx)
+static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
+                                struct extctx_layout *extctx)
 {
        unsigned long sp;
 
@@ -922,7 +923,7 @@ void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
  * Atomically swap in the new signal mask, and wait for a signal.
  */
 
-asmlinkage long sys_rt_sigreturn(void)
+SYSCALL_DEFINE0(rt_sigreturn)
 {
        int sig;
        sigset_t set;
index 6667b0a90f81de12e294d267c7f3f13c6e24fcdc..ef35c871244f0825e998359a3913318bfb872434 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/cpumask.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/profile.h>
 #include <linux/seq_file.h>
 #include <linux/smp.h>
 #include <linux/threads.h>
@@ -556,10 +557,12 @@ void smp_send_stop(void)
        smp_call_function(stop_this_cpu, NULL, 0);
 }
 
+#ifdef CONFIG_PROFILING
 int setup_profiling_timer(unsigned int multiplier)
 {
        return 0;
 }
+#endif
 
 static void flush_tlb_all_ipi(void *info)
 {
index 3fc4211db9895f71bc356b075fbb79f6779bbbe6..b4c5acd7aa3b324d133c0b5bd5e5169bfec5d4f7 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/unistd.h>
 
 #include <asm/asm.h>
+#include <asm/exception.h>
 #include <asm/signal.h>
 #include <asm/switch_to.h>
 #include <asm-generic/syscalls.h>
index c189e03cd5da84b6ebcde9533560d66f98010b5e..3064af94db9c2e14e953a4aad68c2a8d28588447 100644 (file)
@@ -29,7 +29,7 @@ static void constant_event_handler(struct clock_event_device *dev)
 {
 }
 
-irqreturn_t constant_timer_interrupt(int irq, void *data)
+static irqreturn_t constant_timer_interrupt(int irq, void *data)
 {
        int cpu = smp_processor_id();
        struct clock_event_device *cd;
index caa7cd8590788ca39cdc27205951bc1a368fcff7..3fd1660066983b247d1493864a9437e831282e3e 100644 (file)
@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <linux/acpi.h>
 #include <linux/cpu.h>
 #include <linux/cpumask.h>
 #include <linux/init.h>
@@ -7,6 +8,8 @@
 #include <linux/percpu.h>
 #include <asm/bootinfo.h>
 
+#include <acpi/processor.h>
+
 static DEFINE_PER_CPU(struct cpu, cpu_devices);
 
 #ifdef CONFIG_HOTPLUG_CPU
index 65214774ef7c6bade648ccf4f8702cdefc7baac1..aebfc3733a760713836fb5255045e1e9948ca5f4 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/ptrace.h>
 #include <linux/kgdb.h>
 #include <linux/kdebug.h>
-#include <linux/kprobes.h>
 #include <linux/notifier.h>
 #include <linux/irq.h>
 #include <linux/perf_event.h>
@@ -35,6 +34,7 @@
 #include <asm/branch.h>
 #include <asm/break.h>
 #include <asm/cpu.h>
+#include <asm/exception.h>
 #include <asm/fpu.h>
 #include <asm/lbt.h>
 #include <asm/inst.h>
 
 #include "access-helper.h"
 
-extern asmlinkage void handle_ade(void);
-extern asmlinkage void handle_ale(void);
-extern asmlinkage void handle_bce(void);
-extern asmlinkage void handle_sys(void);
-extern asmlinkage void handle_bp(void);
-extern asmlinkage void handle_ri(void);
-extern asmlinkage void handle_fpu(void);
-extern asmlinkage void handle_fpe(void);
-extern asmlinkage void handle_lbt(void);
-extern asmlinkage void handle_lsx(void);
-extern asmlinkage void handle_lasx(void);
-extern asmlinkage void handle_reserved(void);
-extern asmlinkage void handle_watch(void);
-extern asmlinkage void handle_vint(void);
-
 static void show_backtrace(struct task_struct *task, const struct pt_regs *regs,
                           const char *loglvl, bool user)
 {
@@ -439,8 +424,8 @@ static inline void setup_vint_size(unsigned int size)
  * happen together with Overflow or Underflow, and `ptrace' can set
  * any bits.
  */
-void force_fcsr_sig(unsigned long fcsr, void __user *fault_addr,
-                    struct task_struct *tsk)
+static void force_fcsr_sig(unsigned long fcsr,
+                       void __user *fault_addr, struct task_struct *tsk)
 {
        int si_code = FPE_FLTUNK;
 
@@ -458,7 +443,7 @@ void force_fcsr_sig(unsigned long fcsr, void __user *fault_addr,
        force_sig_fault(SIGFPE, si_code, fault_addr);
 }
 
-int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcsr)
+static int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcsr)
 {
        int si_code;
 
@@ -824,7 +809,7 @@ out:
 asmlinkage void noinstr do_ri(struct pt_regs *regs)
 {
        int status = SIGILL;
-       unsigned int opcode = 0;
+       unsigned int __maybe_unused opcode;
        unsigned int __user *era = (unsigned int __user *)exception_era(regs);
        irqentry_state_t state = irqentry_enter(regs);
 
index b1686afcf876663c99e010c40ec84f44d8d55a88..bb2ec86f37a8eb636ef61cbcb9f86fd5869eef4c 100644 (file)
@@ -53,33 +53,6 @@ SECTIONS
        . = ALIGN(PECOFF_SEGMENT_ALIGN);
        _etext = .;
 
-       /*
-        * struct alt_inst entries. From the header (alternative.h):
-        * "Alternative instructions for different CPU types or capabilities"
-        * Think locking instructions on spinlocks.
-        */
-       . = ALIGN(4);
-       .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
-               __alt_instructions = .;
-               *(.altinstructions)
-               __alt_instructions_end = .;
-       }
-
-#ifdef CONFIG_RELOCATABLE
-       . = ALIGN(8);
-       .la_abs : AT(ADDR(.la_abs) - LOAD_OFFSET) {
-               __la_abs_begin = .;
-               *(.la_abs)
-               __la_abs_end = .;
-       }
-#endif
-
-       .got : ALIGN(16) { *(.got) }
-       .plt : ALIGN(16) { *(.plt) }
-       .got.plt : ALIGN(16) { *(.got.plt) }
-
-       .data.rel : { *(.data.rel*) }
-
        . = ALIGN(PECOFF_SEGMENT_ALIGN);
        __init_begin = .;
        __inittext_begin = .;
@@ -94,6 +67,18 @@ SECTIONS
 
        __initdata_begin = .;
 
+       /*
+        * struct alt_inst entries. From the header (alternative.h):
+        * "Alternative instructions for different CPU types or capabilities"
+        * Think locking instructions on spinlocks.
+        */
+       . = ALIGN(4);
+       .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
+               __alt_instructions = .;
+               *(.altinstructions)
+               __alt_instructions_end = .;
+       }
+
        INIT_DATA_SECTION(16)
        .exit.data : {
                EXIT_DATA
@@ -113,6 +98,11 @@ SECTIONS
 
        _sdata = .;
        RO_DATA(4096)
+
+       .got : ALIGN(16) { *(.got) }
+       .plt : ALIGN(16) { *(.plt) }
+       .got.plt : ALIGN(16) { *(.got.plt) }
+
        RW_DATA(1 << CONFIG_L1_CACHE_SHIFT, PAGE_SIZE, THREAD_SIZE)
 
        .rela.dyn : ALIGN(8) {
@@ -121,6 +111,17 @@ SECTIONS
                __rela_dyn_end = .;
        }
 
+       .data.rel : { *(.data.rel*) }
+
+#ifdef CONFIG_RELOCATABLE
+       . = ALIGN(8);
+       .la_abs : AT(ADDR(.la_abs) - LOAD_OFFSET) {
+               __la_abs_begin = .;
+               *(.la_abs)
+               __la_abs_end = .;
+       }
+#endif
+
        .sdata : {
                *(.sdata)
        }
index e6376e3dce862ff83d5995154ab48331a59d4586..1fc2f6813ea027d43ccf24af8aade31f1093df62 100644 (file)
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/kdebug.h>
-#include <linux/kprobes.h>
 #include <linux/perf_event.h>
 #include <linux/uaccess.h>
 #include <linux/kfence.h>
 
 #include <asm/branch.h>
+#include <asm/exception.h>
 #include <asm/mmu_context.h>
 #include <asm/ptrace.h>
 
index ba138117b1247e450431b54c4afe562a56acb312..1e76fcb83093dd6892801200e6027e92d9c68d37 100644 (file)
@@ -50,18 +50,6 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr,
        return (pte_t *) pmd;
 }
 
-/*
- * This function checks for proper alignment of input addr and len parameters.
- */
-int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
-{
-       if (len & ~HPAGE_MASK)
-               return -EINVAL;
-       if (addr & ~HPAGE_MASK)
-               return -EINVAL;
-       return 0;
-}
-
 int pmd_huge(pmd_t pmd)
 {
        return (pmd_val(pmd) & _PAGE_HUGE) != 0;
index 73b0980ab6f5e716650ade71b1a729bd7e892050..70ca7301981106b680bbc506b2ef340d01e73911 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <asm/io.h>
+#include <asm-generic/early_ioremap.h>
 
 void __init __iomem *early_ioremap(u64 phys_addr, unsigned long size)
 {
index da68bc1a464348affc033b559759a784a6080b2b..cc3e81fe0186f4f0fa8de9cedfc75138583ce23f 100644 (file)
@@ -35,6 +35,57 @@ static pgd_t kasan_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
 
 bool kasan_early_stage = true;
 
+void *kasan_mem_to_shadow(const void *addr)
+{
+       if (!kasan_arch_is_ready()) {
+               return (void *)(kasan_early_shadow_page);
+       } else {
+               unsigned long maddr = (unsigned long)addr;
+               unsigned long xrange = (maddr >> XRANGE_SHIFT) & 0xffff;
+               unsigned long offset = 0;
+
+               maddr &= XRANGE_SHADOW_MASK;
+               switch (xrange) {
+               case XKPRANGE_CC_SEG:
+                       offset = XKPRANGE_CC_SHADOW_OFFSET;
+                       break;
+               case XKPRANGE_UC_SEG:
+                       offset = XKPRANGE_UC_SHADOW_OFFSET;
+                       break;
+               case XKVRANGE_VC_SEG:
+                       offset = XKVRANGE_VC_SHADOW_OFFSET;
+                       break;
+               default:
+                       WARN_ON(1);
+                       return NULL;
+               }
+
+               return (void *)((maddr >> KASAN_SHADOW_SCALE_SHIFT) + offset);
+       }
+}
+
+const void *kasan_shadow_to_mem(const void *shadow_addr)
+{
+       unsigned long addr = (unsigned long)shadow_addr;
+
+       if (unlikely(addr > KASAN_SHADOW_END) ||
+               unlikely(addr < KASAN_SHADOW_START)) {
+               WARN_ON(1);
+               return NULL;
+       }
+
+       if (addr >= XKVRANGE_VC_SHADOW_OFFSET)
+               return (void *)(((addr - XKVRANGE_VC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKVRANGE_VC_START);
+       else if (addr >= XKPRANGE_UC_SHADOW_OFFSET)
+               return (void *)(((addr - XKPRANGE_UC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKPRANGE_UC_START);
+       else if (addr >= XKPRANGE_CC_SHADOW_OFFSET)
+               return (void *)(((addr - XKPRANGE_CC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKPRANGE_CC_START);
+       else {
+               WARN_ON(1);
+               return NULL;
+       }
+}
+
 /*
  * Alloc memory for shadow memory page table.
  */
index eb8572e201ea075d5e28a359f65ae8e3d117ebf4..2c0a411f23aa778bb62160bd511252736fc987be 100644 (file)
@@ -261,7 +261,7 @@ unsigned long pcpu_handlers[NR_CPUS];
 #endif
 extern long exception_handlers[VECSIZE * 128 / sizeof(long)];
 
-void setup_tlb_handler(int cpu)
+static void setup_tlb_handler(int cpu)
 {
        setup_ptwalker();
        local_flush_tlb_all();
index e23d06b51a2044016cab18b1704953fb49641826..2a60d7a72f1fa80b96b058eced6c33895693b9b2 100644 (file)
@@ -37,6 +37,7 @@ extern int split_tlb;
 extern int dcache_stride;
 extern int icache_stride;
 extern struct pdc_cache_info cache_info;
+extern struct pdc_btlb_info btlb_info;
 void parisc_setup_cache_timing(void);
 
 #define pdtlb(sr, addr)        asm volatile("pdtlb 0(%%sr%0,%1)" \
diff --git a/arch/parisc/include/asm/mckinley.h b/arch/parisc/include/asm/mckinley.h
deleted file mode 100644 (file)
index 1314390..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef ASM_PARISC_MCKINLEY_H
-#define ASM_PARISC_MCKINLEY_H
-
-/* declared in arch/parisc/kernel/setup.c */
-extern struct proc_dir_entry * proc_mckinley_root;
-
-#endif /*ASM_PARISC_MCKINLEY_H*/
index 269b9a159f01fbec54e164d7baaffcf629c1ce6e..5d2d9737e579dc5e9ba65812dff47d1ac0da8f82 100644 (file)
@@ -44,10 +44,11 @@ int pdc_model_capabilities(unsigned long *capabilities);
 int pdc_model_platform_info(char *orig_prod_num, char *current_prod_num, char *serial_no);
 int pdc_cache_info(struct pdc_cache_info *cache);
 int pdc_spaceid_bits(unsigned long *space_bits);
-#ifndef CONFIG_PA20
 int pdc_btlb_info(struct pdc_btlb_info *btlb);
+int pdc_btlb_insert(unsigned long long vpage, unsigned long physpage, unsigned long len,
+                    unsigned long entry_info, unsigned long slot);
+int pdc_btlb_purge_all(void);
 int pdc_mem_map_hpa(struct pdc_memory_map *r_addr, struct pdc_module_path *mod_path);
-#endif /* !CONFIG_PA20 */
 int pdc_pim_toc11(struct pdc_toc_pim_11 *ret);
 int pdc_pim_toc20(struct pdc_toc_pim_20 *ret);
 int pdc_lan_station_id(char *lan_addr, unsigned long net_hpa);
index d77c43d329743dcc77d47f306a4982b693b7d27c..ff6cbdb6903bca6dceea03000bad4ed97d4b69f2 100644 (file)
@@ -310,6 +310,7 @@ extern void do_syscall_trace_exit(struct pt_regs *);
 struct seq_file;
 extern void early_trap_init(void);
 extern void collect_boot_cpu_data(void);
+extern void btlb_init_per_cpu(void);
 extern int show_cpuinfo (struct seq_file *m, void *v);
 
 /* driver code in driver/parisc */
index fd96706c7234a3e344fa11cf284f8c7e564efbf1..e2d2d7e9bfdea021f3839b25b5aa08b5ed2216dd 100644 (file)
@@ -29,7 +29,7 @@
 struct ioc {
        void __iomem    *ioc_hpa;       /* I/O MMU base address */
        char            *res_map;       /* resource map, bit == pdir entry */
-       u64             *pdir_base;     /* physical base address */
+       __le64          *pdir_base;     /* physical base address */
        unsigned long   ibase;          /* pdir IOV Space base - shared w/lba_pci */
        unsigned long   imask;          /* pdir IOV Space mask - shared w/lba_pci */
 #ifdef ZX1_SUPPORT
@@ -86,6 +86,9 @@ struct sba_device {
        struct ioc              ioc[MAX_IOC];
 };
 
+/* list of SBA's in system, see drivers/parisc/sba_iommu.c */
+extern struct sba_device *sba_list;
+
 #define ASTRO_RUNWAY_PORT      0x582
 #define IKE_MERCED_PORT                0x803
 #define REO_MERCED_PORT                0x804
@@ -110,7 +113,7 @@ static inline int IS_PLUTO(struct parisc_device *d) {
 
 #define SBA_PDIR_VALID_BIT     0x8000000000000000ULL
 
-#define SBA_AGPGART_COOKIE     0x0000badbadc0ffeeULL
+#define SBA_AGPGART_COOKIE     (__force __le64) 0x0000badbadc0ffeeULL
 
 #define SBA_FUNC_ID    0x0000  /* function id */
 #define SBA_FCLASS     0x0008  /* function class, bist, header, rev... */
index 74f74e4d35b72bc353f458b1711a983c4ca97735..5a95b0f62b87ee9a2c3386e629fe24028f622544 100644 (file)
@@ -2,6 +2,21 @@
 #ifndef _ASMPARISC_SHMPARAM_H
 #define _ASMPARISC_SHMPARAM_H
 
+/*
+ * PA-RISC uses virtually indexed & physically tagged (VIPT) caches
+ * which has strict requirements when two pages to the same physical
+ * address are accessed through different mappings. Read the section
+ * "Address Aliasing" in the arch docs for more detail:
+ * PA-RISC 1.1 (page 3-6):
+ * https://parisc.wiki.kernel.org/images-parisc/6/68/Pa11_acd.pdf
+ * PA-RISC 2.0 (page F-5):
+ * https://parisc.wiki.kernel.org/images-parisc/7/73/Parisc2.0.pdf
+ *
+ * For Linux we allow kernel and userspace to map pages on page size
+ * granularity (SHMLBA) but have to ensure that, if two pages are
+ * mapped to the same physical address, the virtual and physical
+ * addresses modulo SHM_COLOUR are identical.
+ */
 #define SHMLBA    PAGE_SIZE    /* attach addr a multiple of this */
 #define SHM_COLOUR 0x00400000  /* shared mappings colouring */
 
index 94652e13c2603ee42fb6dbc1f451ba9738577b7e..757816a7bd4b287d71592be356769bfbb1b0a3ab 100644 (file)
@@ -275,6 +275,8 @@ int main(void)
         * and kernel data on physical huge pages */
 #ifdef CONFIG_HUGETLB_PAGE
        DEFINE(HUGEPAGE_SIZE, 1UL << REAL_HPAGE_SHIFT);
+#elif !defined(CONFIG_64BIT)
+       DEFINE(HUGEPAGE_SIZE, 4*1024*1024);
 #else
        DEFINE(HUGEPAGE_SIZE, PAGE_SIZE);
 #endif
index 442109a489406fc36753a44af8e073a2fc0b377a..268d90a9325b468603b634b86b48980a31b4fba7 100644 (file)
@@ -58,7 +58,7 @@ int pa_serialize_tlb_flushes __ro_after_init;
 
 struct pdc_cache_info cache_info __ro_after_init;
 #ifndef CONFIG_PA20
-static struct pdc_btlb_info btlb_info __ro_after_init;
+struct pdc_btlb_info btlb_info __ro_after_init;
 #endif
 
 DEFINE_STATIC_KEY_TRUE(parisc_has_cache);
@@ -264,12 +264,6 @@ parisc_cache_init(void)
        icache_stride = CAFL_STRIDE(cache_info.ic_conf);
 #undef CAFL_STRIDE
 
-#ifndef CONFIG_PA20
-       if (pdc_btlb_info(&btlb_info) < 0) {
-               memset(&btlb_info, 0, sizeof btlb_info);
-       }
-#endif
-
        if ((boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) ==
                                                PDC_MODEL_NVA_UNSUPPORTED) {
                printk(KERN_WARNING "parisc_cache_init: Only equivalent aliasing supported!\n");
index 8f4b77648491a4b38f15bc1df1c12cfe9c1b0c8e..ed8b759480614beb459a81c0a03278273c75c1f0 100644 (file)
@@ -925,9 +925,9 @@ static __init void qemu_header(void)
        pr_info("#define PARISC_MODEL \"%s\"\n\n",
                        boot_cpu_data.pdc.sys_model_name);
 
+       #define p ((unsigned long *)&boot_cpu_data.pdc.model)
        pr_info("#define PARISC_PDC_MODEL 0x%lx, 0x%lx, 0x%lx, "
                "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx\n\n",
-       #define p ((unsigned long *)&boot_cpu_data.pdc.model)
                p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]);
        #undef p
 
index 8f37e75f2fb9caf51557d46fb7ee6070845e6bba..81078abec521a71c56183b56ff50916e034906df 100644 (file)
@@ -687,7 +687,6 @@ int pdc_spaceid_bits(unsigned long *space_bits)
        return retval;
 }
 
-#ifndef CONFIG_PA20
 /**
  * pdc_btlb_info - Return block TLB information.
  * @btlb: The return buffer.
@@ -696,18 +695,51 @@ int pdc_spaceid_bits(unsigned long *space_bits)
  */
 int pdc_btlb_info(struct pdc_btlb_info *btlb) 
 {
-        int retval;
+       int retval;
        unsigned long flags;
 
-        spin_lock_irqsave(&pdc_lock, flags);
-        retval = mem_pdc_call(PDC_BLOCK_TLB, PDC_BTLB_INFO, __pa(pdc_result), 0);
-        memcpy(btlb, pdc_result, sizeof(*btlb));
-        spin_unlock_irqrestore(&pdc_lock, flags);
+       if (IS_ENABLED(CONFIG_PA20))
+               return PDC_BAD_PROC;
 
-        if(retval < 0) {
-                btlb->max_size = 0;
-        }
-        return retval;
+       spin_lock_irqsave(&pdc_lock, flags);
+       retval = mem_pdc_call(PDC_BLOCK_TLB, PDC_BTLB_INFO, __pa(pdc_result), 0);
+       memcpy(btlb, pdc_result, sizeof(*btlb));
+       spin_unlock_irqrestore(&pdc_lock, flags);
+
+       if(retval < 0) {
+               btlb->max_size = 0;
+       }
+       return retval;
+}
+
+int pdc_btlb_insert(unsigned long long vpage, unsigned long physpage, unsigned long len,
+                   unsigned long entry_info, unsigned long slot)
+{
+       int retval;
+       unsigned long flags;
+
+       if (IS_ENABLED(CONFIG_PA20))
+               return PDC_BAD_PROC;
+
+       spin_lock_irqsave(&pdc_lock, flags);
+       retval = mem_pdc_call(PDC_BLOCK_TLB, PDC_BTLB_INSERT, (unsigned long) (vpage >> 32),
+                             (unsigned long) vpage, physpage, len, entry_info, slot);
+       spin_unlock_irqrestore(&pdc_lock, flags);
+       return retval;
+}
+
+int pdc_btlb_purge_all(void)
+{
+       int retval;
+       unsigned long flags;
+
+       if (IS_ENABLED(CONFIG_PA20))
+               return PDC_BAD_PROC;
+
+       spin_lock_irqsave(&pdc_lock, flags);
+       retval = mem_pdc_call(PDC_BLOCK_TLB, PDC_BTLB_PURGE_ALL);
+       spin_unlock_irqrestore(&pdc_lock, flags);
+       return retval;
 }
 
 /**
@@ -728,6 +760,9 @@ int pdc_mem_map_hpa(struct pdc_memory_map *address,
         int retval;
        unsigned long flags;
 
+       if (IS_ENABLED(CONFIG_PA20))
+               return PDC_BAD_PROC;
+
         spin_lock_irqsave(&pdc_lock, flags);
         memcpy(pdc_result2, mod_path, sizeof(*mod_path));
         retval = mem_pdc_call(PDC_MEM_MAP, PDC_MEM_MAP_HPA, __pa(pdc_result),
@@ -737,7 +772,6 @@ int pdc_mem_map_hpa(struct pdc_memory_map *address,
 
         return retval;
 }
-#endif /* !CONFIG_PA20 */
 
 /**
  * pdc_lan_station_id - Get the LAN address.
index fd15fd4bbb61b8f4cd7567b20a7b6d29f36b7864..a171bf3c6b318da29a6162bd71de0fd46ad15afc 100644 (file)
@@ -180,10 +180,10 @@ $pgt_fill_loop:
        std             %dp,0x18(%r10)
 #endif
 
-#ifdef CONFIG_64BIT
-       /* Get PDCE_PROC for monarch CPU. */
 #define MEM_PDC_LO 0x388
 #define MEM_PDC_HI 0x35C
+#ifdef CONFIG_64BIT
+       /* Get PDCE_PROC for monarch CPU. */
        ldw             MEM_PDC_LO(%r0),%r3
        ldw             MEM_PDC_HI(%r0),%r10
        depd            %r10, 31, 32, %r3        /* move to upper word */
@@ -269,7 +269,17 @@ stext_pdc_ret:
        tovirt_r1       %r6
        mtctl           %r6,%cr30               /* restore task thread info */
 #endif
-       
+
+#ifndef CONFIG_64BIT
+       /* clear all BTLBs */
+       ldi             PDC_BLOCK_TLB,%arg0
+       load32          PA(stext_pdc_btlb_ret), %rp
+       ldw             MEM_PDC_LO(%r0),%r3
+       bv              (%r3)
+       ldi             PDC_BTLB_PURGE_ALL,%arg1
+stext_pdc_btlb_ret:
+#endif
+
        /* PARANOID: clear user scratch/user space SR's */
        mtsp    %r0,%sr0
        mtsp    %r0,%sr1
index 12c4d4104ade4a6fbb9504cd5a7ad5e06083f587..2f81bfd4f15e17bc0b0ec3fd1b524e571c2924ed 100644 (file)
@@ -365,7 +365,7 @@ union irq_stack_union {
        volatile unsigned int lock[1];
 };
 
-DEFINE_PER_CPU(union irq_stack_union, irq_stack_union) = {
+static DEFINE_PER_CPU(union irq_stack_union, irq_stack_union) = {
                .slock = { 1,1,1,1 },
        };
 #endif
index a0e2d37c5b3b530818b22069b09bba9e88418936..1fc89fa2c2d21420f8475685d24a2095235cc004 100644 (file)
@@ -368,6 +368,8 @@ int init_per_cpu(int cpunum)
        /* FUTURE: Enable Performance Monitor : ccr bit 0x20 */
        init_percpu_prof(cpunum);
 
+       btlb_init_per_cpu();
+
        return ret;
 }
 
index 1aaa2ca0980033d337597b9c8b2f14bea36c628e..58694d1989c23351772602e369028402bced2030 100644 (file)
@@ -154,6 +154,7 @@ SECTIONS
        }
 
        /* End of data section */
+       . = ALIGN(PAGE_SIZE);
        _edata = .;
 
        /* BSS */
index a088c243edeaa40733ead6e9200ef160cf76f6c0..a2a3e89f2d9ab371a5a62ed24b7fa29f459726ab 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/sections.h>
 #include <asm/msgbuf.h>
 #include <asm/sparsemem.h>
+#include <asm/asm-offsets.h>
 
 extern int  data_start;
 extern void parisc_kernel_start(void); /* Kernel entry point in head.S */
@@ -720,6 +721,77 @@ void __init paging_init(void)
        parisc_bootmem_free();
 }
 
+static void alloc_btlb(unsigned long start, unsigned long end, int *slot,
+                       unsigned long entry_info)
+{
+       const int slot_max = btlb_info.fixed_range_info.num_comb;
+       int min_num_pages = btlb_info.min_size;
+       unsigned long size;
+
+       /* map at minimum 4 pages */
+       if (min_num_pages < 4)
+               min_num_pages = 4;
+
+       size = HUGEPAGE_SIZE;
+       while (start < end && *slot < slot_max && size >= PAGE_SIZE) {
+               /* starting address must have same alignment as size! */
+               /* if correctly aligned and fits in double size, increase */
+               if (((start & (2 * size - 1)) == 0) &&
+                   (end - start) >= (2 * size)) {
+                       size <<= 1;
+                       continue;
+               }
+               /* if current size alignment is too big, try smaller size */
+               if ((start & (size - 1)) != 0) {
+                       size >>= 1;
+                       continue;
+               }
+               if ((end - start) >= size) {
+                       if ((size >> PAGE_SHIFT) >= min_num_pages)
+                               pdc_btlb_insert(start >> PAGE_SHIFT, __pa(start) >> PAGE_SHIFT,
+                                       size >> PAGE_SHIFT, entry_info, *slot);
+                       (*slot)++;
+                       start += size;
+                       continue;
+               }
+               size /= 2;
+               continue;
+       }
+}
+
+void btlb_init_per_cpu(void)
+{
+       unsigned long s, t, e;
+       int slot;
+
+       /* BTLBs are not available on 64-bit CPUs */
+       if (IS_ENABLED(CONFIG_PA20))
+               return;
+       else if (pdc_btlb_info(&btlb_info) < 0) {
+               memset(&btlb_info, 0, sizeof btlb_info);
+       }
+
+       /* insert BLTLBs for code and data segments */
+       s = (uintptr_t) dereference_function_descriptor(&_stext);
+       e = (uintptr_t) dereference_function_descriptor(&_etext);
+       t = (uintptr_t) dereference_function_descriptor(&_sdata);
+       BUG_ON(t != e);
+
+       /* code segments */
+       slot = 0;
+       alloc_btlb(s, e, &slot, 0x13800000);
+
+       /* sanity check */
+       t = (uintptr_t) dereference_function_descriptor(&_edata);
+       e = (uintptr_t) dereference_function_descriptor(&__bss_start);
+       BUG_ON(t != e);
+
+       /* data segments */
+       s = (uintptr_t) dereference_function_descriptor(&_sdata);
+       e = (uintptr_t) dereference_function_descriptor(&__bss_stop);
+       alloc_btlb(s, e, &slot, 0x11800000);
+}
+
 #ifdef CONFIG_PA20
 
 /*
index 54b9387c3691643ae486248d60e5482e011cc060..3aaadfd2c8eb24504774235228eb43850ea7de2a 100644 (file)
@@ -255,7 +255,7 @@ config PPC
        select HAVE_KPROBES
        select HAVE_KPROBES_ON_FTRACE
        select HAVE_KRETPROBES
-       select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if HAVE_OBJTOOL_MCOUNT
+       select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if HAVE_OBJTOOL_MCOUNT && (!ARCH_USING_PATCHABLE_FUNCTION_ENTRY || (!CC_IS_GCC || GCC_VERSION >= 110100))
        select HAVE_LIVEPATCH                   if HAVE_DYNAMIC_FTRACE_WITH_REGS
        select HAVE_MOD_ARCH_SPECIFIC
        select HAVE_NMI                         if PERF_EVENTS || (PPC64 && PPC_BOOK3S)
index b8513dc3e53ac8cb654177591b1513b5a1f17c49..a1318ce18d0e61b34f49869b12ae4dcfd3cc5f95 100644 (file)
@@ -230,13 +230,15 @@ void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs)
        struct arch_hw_breakpoint *info;
        int i;
 
+       preempt_disable();
+
        for (i = 0; i < nr_wp_slots(); i++) {
                struct perf_event *bp = __this_cpu_read(bp_per_reg[i]);
 
                if (unlikely(bp && counter_arch_bp(bp)->perf_single_step))
                        goto reset;
        }
-       return;
+       goto out;
 
 reset:
        regs_set_return_msr(regs, regs->msr & ~MSR_SE);
@@ -245,6 +247,9 @@ reset:
                __set_breakpoint(i, info);
                info->perf_single_step = false;
        }
+
+out:
+       preempt_enable();
 }
 
 static bool is_larx_stcx_instr(int type)
@@ -363,6 +368,11 @@ static void handle_p10dd1_spurious_exception(struct perf_event **bp,
        }
 }
 
+/*
+ * Handle a DABR or DAWR exception.
+ *
+ * Called in atomic context.
+ */
 int hw_breakpoint_handler(struct die_args *args)
 {
        bool err = false;
@@ -490,6 +500,8 @@ NOKPROBE_SYMBOL(hw_breakpoint_handler);
 
 /*
  * Handle single-step exceptions following a DABR hit.
+ *
+ * Called in atomic context.
  */
 static int single_step_dabr_instruction(struct die_args *args)
 {
@@ -541,6 +553,8 @@ NOKPROBE_SYMBOL(single_step_dabr_instruction);
 
 /*
  * Handle debug exception notifications.
+ *
+ * Called in atomic context.
  */
 int hw_breakpoint_exceptions_notify(
                struct notifier_block *unused, unsigned long val, void *data)
index a74623025f3ab87b5a3375bab26e19c25b1ae173..9e51801c49152e32236b4ef5aa8a89ee05501445 100644 (file)
@@ -131,8 +131,13 @@ void wp_get_instr_detail(struct pt_regs *regs, ppc_inst_t *instr,
                         int *type, int *size, unsigned long *ea)
 {
        struct instruction_op op;
+       int err;
 
-       if (__get_user_instr(*instr, (void __user *)regs->nip))
+       pagefault_disable();
+       err = __get_user_instr(*instr, (void __user *)regs->nip);
+       pagefault_enable();
+
+       if (err)
                return;
 
        analyse_instr(&op, regs, *instr);
index eeff136b83d97b22343cf1b7ce8b3b0144f5943c..64ff37721fd06f4914ba8bf6b80abc19f1b2cc32 100644 (file)
@@ -1512,23 +1512,11 @@ static void do_program_check(struct pt_regs *regs)
                        return;
                }
 
-               if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE) && user_mode(regs)) {
-                       ppc_inst_t insn;
-
-                       if (get_user_instr(insn, (void __user *)regs->nip)) {
-                               _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
-                               return;
-                       }
-
-                       if (ppc_inst_primary_opcode(insn) == 31 &&
-                           get_xop(ppc_inst_val(insn)) == OP_31_XOP_HASHCHK) {
-                               _exception(SIGILL, regs, ILL_ILLOPN, regs->nip);
-                               return;
-                       }
+               /* User mode considers other cases after enabling IRQs */
+               if (!user_mode(regs)) {
+                       _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
+                       return;
                }
-
-               _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
-               return;
        }
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        if (reason & REASON_TM) {
@@ -1561,16 +1549,44 @@ static void do_program_check(struct pt_regs *regs)
 
        /*
         * If we took the program check in the kernel skip down to sending a
-        * SIGILL. The subsequent cases all relate to emulating instructions
-        * which we should only do for userspace. We also do not want to enable
-        * interrupts for kernel faults because that might lead to further
-        * faults, and loose the context of the original exception.
+        * SIGILL. The subsequent cases all relate to user space, such as
+        * emulating instructions which we should only do for user space. We
+        * also do not want to enable interrupts for kernel faults because that
+        * might lead to further faults, and loose the context of the original
+        * exception.
         */
        if (!user_mode(regs))
                goto sigill;
 
        interrupt_cond_local_irq_enable(regs);
 
+       /*
+        * (reason & REASON_TRAP) is mostly handled before enabling IRQs,
+        * except get_user_instr() can sleep so we cannot reliably inspect the
+        * current instruction in that context. Now that we know we are
+        * handling a user space trap and can sleep, we can check if the trap
+        * was a hashchk failure.
+        */
+       if (reason & REASON_TRAP) {
+               if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE)) {
+                       ppc_inst_t insn;
+
+                       if (get_user_instr(insn, (void __user *)regs->nip)) {
+                               _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
+                               return;
+                       }
+
+                       if (ppc_inst_primary_opcode(insn) == 31 &&
+                           get_xop(ppc_inst_val(insn)) == OP_31_XOP_HASHCHK) {
+                               _exception(SIGILL, regs, ILL_ILLOPN, regs->nip);
+                               return;
+                       }
+               }
+
+               _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
+               return;
+       }
+
        /* (reason & REASON_ILLEGAL) would be the obvious thing here,
         * but there seems to be a hardware bug on the 405GP (RevD)
         * that means ESR is sometimes set incorrectly - either to
index 317175791d23c34912bf7b7d9ac8a40e30648e41..3449be7c0d51f7e9e62112523a0f182891f4bf8d 100644 (file)
@@ -1418,7 +1418,7 @@ static int h_24x7_event_init(struct perf_event *event)
        }
 
        domain = event_get_domain(event);
-       if (domain >= HV_PERF_DOMAIN_MAX) {
+       if (domain  == 0 || domain >= HV_PERF_DOMAIN_MAX) {
                pr_devel("invalid domain %d\n", domain);
                return -EINVAL;
        }
index d9f1a2a83158aa47b6763e6fe7180617096ac73f..1824536cf6f21f80d6ececef62697be5ed3396de 100644 (file)
@@ -2,6 +2,7 @@
 menuconfig PPC_82xx
        bool "82xx-based boards (PQ II)"
        depends on PPC_BOOK3S_32
+       select FSL_SOC
 
 if PPC_82xx
 
@@ -9,7 +10,6 @@ config EP8248E
        bool "Embedded Planet EP8248E (a.k.a. CWH-PPC-8248N-VE)"
        select CPM2
        select PPC_INDIRECT_PCI if PCI
-       select FSL_SOC
        select PHYLIB if NETDEVICES
        select MDIO_BITBANG if PHYLIB
        help
@@ -22,7 +22,6 @@ config MGCOGE
        bool "Keymile MGCOGE"
        select CPM2
        select PPC_INDIRECT_PCI if PCI
-       select FSL_SOC
        help
          This enables support for the Keymile MGCOGE board.
 
index e2ecd01bfac771bc91a34949167906d744891c72..b55b434f0059108342229b1e2013e351a7b81961 100644 (file)
@@ -105,7 +105,7 @@ asm volatile(ALTERNATIVE(                                           \
  * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
  *   0000001    01001      rs1       000      00000  0001011
  * dcache.cva rs1 (clean, virtual address)
- *   0000001    00100      rs1       000      00000  0001011
+ *   0000001    00101      rs1       000      00000  0001011
  *
  * dcache.cipa rs1 (clean then invalidate, physical address)
  * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
@@ -118,7 +118,7 @@ asm volatile(ALTERNATIVE(                                           \
  *   0000000    11001     00000      000      00000  0001011
  */
 #define THEAD_inval_A0 ".long 0x0265000b"
-#define THEAD_clean_A0 ".long 0x0245000b"
+#define THEAD_clean_A0 ".long 0x0255000b"
 #define THEAD_flush_A0 ".long 0x0275000b"
 #define THEAD_SYNC_S   ".long 0x0190000b"
 
index f4099059ed8f2507913ecfbb3713249feda33373..e60fbd8660c4a531c6deef3938c45afe2e158839 100644 (file)
@@ -98,7 +98,13 @@ static int elf_find_pbase(struct kimage *image, unsigned long kernel_len,
        kbuf.image = image;
        kbuf.buf_min = lowest_paddr;
        kbuf.buf_max = ULONG_MAX;
-       kbuf.buf_align = PAGE_SIZE;
+
+       /*
+        * Current riscv boot protocol requires 2MB alignment for
+        * RV64 and 4MB alignment for RV32
+        *
+        */
+       kbuf.buf_align = PMD_SIZE;
        kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
        kbuf.memsz = ALIGN(kernel_len, PAGE_SIZE);
        kbuf.top_down = false;
index 1b7e9fa265cbb8dd68b30cc06ed8b7b00dc03fba..b7e0e03c69b1e50c7fa937ca513129259678aad3 100644 (file)
@@ -460,8 +460,11 @@ static int riscv_vcpu_get_isa_ext_single(struct kvm_vcpu *vcpu,
            reg_num >= ARRAY_SIZE(kvm_isa_ext_arr))
                return -ENOENT;
 
-       *reg_val = 0;
        host_isa_ext = kvm_isa_ext_arr[reg_num];
+       if (!__riscv_isa_extension_available(NULL, host_isa_ext))
+               return -ENOENT;
+
+       *reg_val = 0;
        if (__riscv_isa_extension_available(vcpu->arch.isa, host_isa_ext))
                *reg_val = 1; /* Mark the given extension as available */
 
@@ -842,7 +845,7 @@ static int copy_isa_ext_reg_indices(const struct kvm_vcpu *vcpu,
                u64 reg = KVM_REG_RISCV | size | KVM_REG_RISCV_ISA_EXT | i;
 
                isa_ext = kvm_isa_ext_arr[i];
-               if (!__riscv_isa_extension_available(vcpu->arch.isa, isa_ext))
+               if (!__riscv_isa_extension_available(NULL, isa_ext))
                        continue;
 
                if (uindices) {
index af2fbe48e16cd9fc22eecdc1be964c8fae4cbb5c..438cd92e60801bd3c12cd1f891c5a9009fe115f8 100644 (file)
@@ -40,23 +40,25 @@ CONFIG_SCHED_AUTOGROUP=y
 CONFIG_EXPERT=y
 # CONFIG_SYSFS_SYSCALL is not set
 CONFIG_PROFILING=y
+CONFIG_KEXEC_FILE=y
+CONFIG_KEXEC_SIG=y
+CONFIG_CRASH_DUMP=y
 CONFIG_LIVEPATCH=y
 CONFIG_MARCH_ZEC12=y
 CONFIG_TUNE_ZEC12=y
 CONFIG_NR_CPUS=512
 CONFIG_NUMA=y
 CONFIG_HZ_100=y
-CONFIG_KEXEC_FILE=y
-CONFIG_KEXEC_SIG=y
+CONFIG_CERT_STORE=y
 CONFIG_EXPOLINE=y
 CONFIG_EXPOLINE_AUTO=y
 CONFIG_CHSC_SCH=y
 CONFIG_VFIO_CCW=m
 CONFIG_VFIO_AP=m
-CONFIG_CRASH_DUMP=y
 CONFIG_PROTECTED_VIRTUALIZATION_GUEST=y
 CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
+CONFIG_S390_HYPFS_FS=y
 CONFIG_KVM=m
 CONFIG_S390_UNWIND_SELFTEST=m
 CONFIG_S390_KPROBES_SANITY_TEST=m
@@ -434,6 +436,7 @@ CONFIG_SCSI_DH_EMC=m
 CONFIG_SCSI_DH_ALUA=m
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
+# CONFIG_MD_BITMAP_FILE is not set
 CONFIG_MD_LINEAR=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
@@ -577,6 +580,7 @@ CONFIG_SOFT_WATCHDOG=m
 CONFIG_DIAG288_WATCHDOG=m
 # CONFIG_DRM_DEBUG_MODESET_LOCK is not set
 CONFIG_FB=y
+# CONFIG_FB_DEVICE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 # CONFIG_HID_SUPPORT is not set
@@ -647,6 +651,7 @@ CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_TMPFS_INODE64=y
+CONFIG_TMPFS_QUOTA=y
 CONFIG_HUGETLBFS=y
 CONFIG_ECRYPT_FS=m
 CONFIG_CRAMFS=m
@@ -703,6 +708,7 @@ CONFIG_IMA_WRITE_POLICY=y
 CONFIG_IMA_APPRAISE=y
 CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"
 CONFIG_INIT_STACK_NONE=y
+CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_CRYPTO_USER=m
 # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
 CONFIG_CRYPTO_PCRYPT=m
@@ -825,9 +831,9 @@ CONFIG_LOCK_STAT=y
 CONFIG_DEBUG_ATOMIC_SLEEP=y
 CONFIG_DEBUG_LOCKING_API_SELFTESTS=y
 CONFIG_DEBUG_IRQFLAGS=y
+CONFIG_DEBUG_LIST=y
 CONFIG_DEBUG_SG=y
 CONFIG_DEBUG_NOTIFIERS=y
-CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_DEBUG_CREDENTIALS=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_REF_SCALE_TEST=m
index 3f263b767a4c4198f098a017dd83db427ecbcc37..1b8150e50f6a65a9d0dadbbf6bb1ee7e2785f8d3 100644 (file)
@@ -38,23 +38,25 @@ CONFIG_SCHED_AUTOGROUP=y
 CONFIG_EXPERT=y
 # CONFIG_SYSFS_SYSCALL is not set
 CONFIG_PROFILING=y
+CONFIG_KEXEC_FILE=y
+CONFIG_KEXEC_SIG=y
+CONFIG_CRASH_DUMP=y
 CONFIG_LIVEPATCH=y
 CONFIG_MARCH_ZEC12=y
 CONFIG_TUNE_ZEC12=y
 CONFIG_NR_CPUS=512
 CONFIG_NUMA=y
 CONFIG_HZ_100=y
-CONFIG_KEXEC_FILE=y
-CONFIG_KEXEC_SIG=y
+CONFIG_CERT_STORE=y
 CONFIG_EXPOLINE=y
 CONFIG_EXPOLINE_AUTO=y
 CONFIG_CHSC_SCH=y
 CONFIG_VFIO_CCW=m
 CONFIG_VFIO_AP=m
-CONFIG_CRASH_DUMP=y
 CONFIG_PROTECTED_VIRTUALIZATION_GUEST=y
 CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
+CONFIG_S390_HYPFS_FS=y
 CONFIG_KVM=m
 CONFIG_S390_UNWIND_SELFTEST=m
 CONFIG_S390_KPROBES_SANITY_TEST=m
@@ -424,6 +426,7 @@ CONFIG_SCSI_DH_EMC=m
 CONFIG_SCSI_DH_ALUA=m
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
+# CONFIG_MD_BITMAP_FILE is not set
 CONFIG_MD_LINEAR=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
@@ -566,6 +569,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y
 CONFIG_SOFT_WATCHDOG=m
 CONFIG_DIAG288_WATCHDOG=m
 CONFIG_FB=y
+# CONFIG_FB_DEVICE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 # CONFIG_HID_SUPPORT is not set
@@ -632,6 +636,7 @@ CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_TMPFS_INODE64=y
+CONFIG_TMPFS_QUOTA=y
 CONFIG_HUGETLBFS=y
 CONFIG_CONFIGFS_FS=m
 CONFIG_ECRYPT_FS=m
@@ -687,6 +692,7 @@ CONFIG_IMA_WRITE_POLICY=y
 CONFIG_IMA_APPRAISE=y
 CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"
 CONFIG_INIT_STACK_NONE=y
+CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_CRYPTO_FIPS=y
 CONFIG_CRYPTO_USER=m
 # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
@@ -781,7 +787,6 @@ CONFIG_PTDUMP_DEBUGFS=y
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_PANIC_ON_OOPS=y
 CONFIG_TEST_LOCKUP=m
-CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_REF_SCALE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
index e62fb20151028fd53cbf28b065694ee81b778f01..b831083b4edd8b796b949333b5ca279c96eda237 100644 (file)
@@ -8,6 +8,7 @@ CONFIG_BPF_SYSCALL=y
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_CRASH_DUMP=y
 CONFIG_MARCH_ZEC12=y
 CONFIG_TUNE_ZEC12=y
 # CONFIG_COMPAT is not set
@@ -15,9 +16,8 @@ CONFIG_NR_CPUS=2
 CONFIG_HZ_100=y
 # CONFIG_CHSC_SCH is not set
 # CONFIG_SCM_BUS is not set
-CONFIG_CRASH_DUMP=y
 # CONFIG_PFAULT is not set
-# CONFIG_S390_HYPFS_FS is not set
+# CONFIG_S390_HYPFS is not set
 # CONFIG_VIRTUALIZATION is not set
 # CONFIG_S390_GUEST is not set
 # CONFIG_SECCOMP is not set
index 3986a044eb367f5ab08f3f8b0e9ac58f834e1236..554447768bddc7d0d27aa16ddbf0727c6ef95d4e 100644 (file)
@@ -432,15 +432,16 @@ static char *get_key_description(struct vcssb *vcssb, const struct vce *vce)
        char *desc;
 
        cs_token = vcssb->cs_token;
-       /* Description string contains "%64s:%04u:%08u\0". */
+       /* Description string contains "%64s:%05u:%010u\0". */
        name_len = sizeof(vce->vce_hdr.vc_name);
-       len = name_len + 1 + 4 + 1 + 8 + 1;
+       len = name_len + 1 + 5 + 1 + 10 + 1;
        desc = kmalloc(len, GFP_KERNEL);
        if (!desc)
                return NULL;
 
        memcpy(desc, vce->vce_hdr.vc_name, name_len);
-       sprintf(desc + name_len, ":%04u:%08u", vce->vce_hdr.vc_index, cs_token);
+       snprintf(desc + name_len, len - name_len, ":%05u:%010u",
+                vce->vce_hdr.vc_index, cs_token);
 
        return desc;
 }
index c33b3daa4ad1a3e6db7e319e229fe08db204dfe8..33d20f34560fd5cb5d69dfe09ba08a16c9e0b496 100644 (file)
@@ -72,8 +72,8 @@ __ioremap_29bit(phys_addr_t offset, unsigned long size, pgprot_t prot)
 #define __ioremap_29bit(offset, size, prot)            NULL
 #endif /* CONFIG_29BIT */
 
-void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
-                          unsigned long prot)
+void __iomem __ref *ioremap_prot(phys_addr_t phys_addr, size_t size,
+                                unsigned long prot)
 {
        void __iomem *mapped;
        pgprot_t pgprot = __pgprot(prot);
index 982b777eadc7a16cc4b4b52f300b9c816f0cfd2f..66bfabae8814919c61902da3cdc77a45d9efa775 100644 (file)
@@ -1945,6 +1945,7 @@ config EFI
        select UCS2_STRING
        select EFI_RUNTIME_WRAPPERS
        select ARCH_USE_MEMREMAP_PROT
+       select EFI_RUNTIME_MAP if KEXEC_CORE
        help
          This enables the kernel to use EFI runtime services that are
          available (such as the EFI variable services).
@@ -2020,7 +2021,6 @@ config EFI_MAX_FAKE_MEM
 config EFI_RUNTIME_MAP
        bool "Export EFI runtime maps to sysfs" if EXPERT
        depends on EFI
-       default KEXEC_CORE
        help
          Export EFI runtime memory regions to /sys/firmware/efi/runtime-map.
          That memory map is required by the 2nd kernel to set up EFI virtual
index bcc956c17872bbd3939b33c59889d39cfb3641ac..08f93b0401bbd3498b0754e20780e2d585e064f1 100644 (file)
@@ -59,6 +59,14 @@ static void *alloc_pgt_page(void *context)
                return NULL;
        }
 
+       /* Consumed more tables than expected? */
+       if (pages->pgt_buf_offset == BOOT_PGT_SIZE_WARN) {
+               debug_putstr("pgt_buf running low in " __FILE__ "\n");
+               debug_putstr("Need to raise BOOT_PGT_SIZE?\n");
+               debug_putaddr(pages->pgt_buf_offset);
+               debug_putaddr(pages->pgt_buf_size);
+       }
+
        entry = pages->pgt_buf + pages->pgt_buf_offset;
        pages->pgt_buf_offset += PAGE_SIZE;
 
index 6c2826417b3376cb70d53df8006f5998a0e33d9c..93c60c0c9d4a7a25d91aef2d948d648e08006abe 100644 (file)
@@ -294,7 +294,7 @@ static void __xen_pv_evtchn_do_upcall(struct pt_regs *regs)
 
        inc_irq_stat(irq_hv_callback_count);
 
-       xen_hvm_evtchn_do_upcall();
+       xen_evtchn_do_upcall();
 
        set_irq_regs(old_regs);
 }
index 4ae14339cb8cc72da4df2442a363ca2f728573c6..b3a7cfb0d99e01a8f54fa540983ca9a4b4010f50 100644 (file)
 #ifdef CONFIG_X86_64
 # define BOOT_STACK_SIZE       0x4000
 
+/*
+ * Used by decompressor's startup_32() to allocate page tables for identity
+ * mapping of the 4G of RAM in 4-level paging mode:
+ * - 1 level4 table;
+ * - 1 level3 table;
+ * - 4 level2 table that maps everything with 2M pages;
+ *
+ * The additional level5 table needed for 5-level paging is allocated from
+ * trampoline_32bit memory.
+ */
 # define BOOT_INIT_PGT_SIZE    (6*4096)
-# ifdef CONFIG_RANDOMIZE_BASE
+
 /*
- * Assuming all cross the 512GB boundary:
- * 1 page for level4
- * (2+2)*4 pages for kernel, param, cmd_line, and randomized kernel
- * 2 pages for first 2M (video RAM: CONFIG_X86_VERBOSE_BOOTUP).
- * Total is 19 pages.
+ * Total number of page tables kernel_add_identity_map() can allocate,
+ * including page tables consumed by startup_32().
+ *
+ * Worst-case scenario:
+ *  - 5-level paging needs 1 level5 table;
+ *  - KASLR needs to map kernel, boot_params, cmdline and randomized kernel,
+ *    assuming all of them cross 256T boundary:
+ *    + 4*2 level4 table;
+ *    + 4*2 level3 table;
+ *    + 4*2 level2 table;
+ *  - X86_VERBOSE_BOOTUP needs to map the first 2M (video RAM):
+ *    + 1 level4 table;
+ *    + 1 level3 table;
+ *    + 1 level2 table;
+ * Total: 28 tables
+ *
+ * Add 4 spare table in case decompressor touches anything beyond what is
+ * accounted above. Warn if it happens.
  */
-#  ifdef CONFIG_X86_VERBOSE_BOOTUP
-#   define BOOT_PGT_SIZE       (19*4096)
-#  else /* !CONFIG_X86_VERBOSE_BOOTUP */
-#   define BOOT_PGT_SIZE       (17*4096)
-#  endif
-# else /* !CONFIG_RANDOMIZE_BASE */
-#  define BOOT_PGT_SIZE                BOOT_INIT_PGT_SIZE
-# endif
+# define BOOT_PGT_SIZE_WARN    (28*4096)
+# define BOOT_PGT_SIZE         (32*4096)
 
 #else /* !CONFIG_X86_64 */
 # define BOOT_STACK_SIZE       0x1000
index b0994ae3bc23f84df03331b9ffc36b3e1c9d62f9..c4555b269a1b247430f50dcf5934855823e1eba6 100644 (file)
@@ -91,19 +91,6 @@ static inline void efi_fpu_end(void)
 
 #ifdef CONFIG_X86_32
 #define EFI_X86_KERNEL_ALLOC_LIMIT             (SZ_512M - 1)
-
-#define arch_efi_call_virt_setup()                                     \
-({                                                                     \
-       efi_fpu_begin();                                                \
-       firmware_restrict_branch_speculation_start();                   \
-})
-
-#define arch_efi_call_virt_teardown()                                  \
-({                                                                     \
-       firmware_restrict_branch_speculation_end();                     \
-       efi_fpu_end();                                                  \
-})
-
 #else /* !CONFIG_X86_32 */
 #define EFI_X86_KERNEL_ALLOC_LIMIT             EFI_ALLOC_LIMIT
 
@@ -116,14 +103,6 @@ extern bool efi_disable_ibt_for_runtime;
        __efi_call(__VA_ARGS__);                                        \
 })
 
-#define arch_efi_call_virt_setup()                                     \
-({                                                                     \
-       efi_sync_low_kernel_mappings();                                 \
-       efi_fpu_begin();                                                \
-       firmware_restrict_branch_speculation_start();                   \
-       efi_enter_mm();                                                 \
-})
-
 #undef arch_efi_call_virt
 #define arch_efi_call_virt(p, f, args...) ({                           \
        u64 ret, ibt = ibt_save(efi_disable_ibt_for_runtime);           \
@@ -132,13 +111,6 @@ extern bool efi_disable_ibt_for_runtime;
        ret;                                                            \
 })
 
-#define arch_efi_call_virt_teardown()                                  \
-({                                                                     \
-       efi_leave_mm();                                                 \
-       firmware_restrict_branch_speculation_end();                     \
-       efi_fpu_end();                                                  \
-})
-
 #ifdef CONFIG_KASAN
 /*
  * CONFIG_KASAN may redefine memset to __memset.  __memset function is present
@@ -168,8 +140,8 @@ extern void efi_delete_dummy_variable(void);
 extern void efi_crash_gracefully_on_page_fault(unsigned long phys_addr);
 extern void efi_free_boot_services(void);
 
-void efi_enter_mm(void);
-void efi_leave_mm(void);
+void arch_efi_call_virt_setup(void);
+void arch_efi_call_virt_teardown(void);
 
 /* kexec external ABI */
 struct efi_setup_data {
index 1a4def36d5bb26e056989edb25ae39afc50b0eae..17715cb8731d5d2c7d60caeebf6e340158888ef5 100644 (file)
@@ -1419,7 +1419,6 @@ struct kvm_arch {
         * the thread holds the MMU lock in write mode.
         */
        spinlock_t tdp_mmu_pages_lock;
-       struct workqueue_struct *tdp_mmu_zap_wq;
 #endif /* CONFIG_X86_64 */
 
        /*
@@ -1835,7 +1834,7 @@ void kvm_mmu_vendor_module_exit(void);
 
 void kvm_mmu_destroy(struct kvm_vcpu *vcpu);
 int kvm_mmu_create(struct kvm_vcpu *vcpu);
-int kvm_mmu_init_vm(struct kvm *kvm);
+void kvm_mmu_init_vm(struct kvm *kvm);
 void kvm_mmu_uninit_vm(struct kvm *kvm);
 
 void kvm_mmu_after_set_cpuid(struct kvm_vcpu *vcpu);
index 97a3de7892d3ff376c3058d759141b07630c0760..571fe4d2d2328c3b4899faf8085e0181403ed003 100644 (file)
@@ -8,6 +8,14 @@
 #undef notrace
 #define notrace __attribute__((no_instrument_function))
 
+#ifdef CONFIG_64BIT
+/*
+ * The generic version tends to create spurious ENDBR instructions under
+ * certain conditions.
+ */
+#define _THIS_IP_ ({ unsigned long __here; asm ("lea 0(%%rip), %0" : "=r" (__here)); __here; })
+#endif
+
 #ifdef CONFIG_X86_32
 #define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
 #endif /* CONFIG_X86_32 */
        CFI_POST_PADDING                                        \
        SYM_FUNC_END(__cfi_##name)
 
+/* UML needs to be able to override memcpy() and friends for KASAN. */
+#ifdef CONFIG_UML
+# define SYM_FUNC_ALIAS_MEMFUNC        SYM_FUNC_ALIAS_WEAK
+#else
+# define SYM_FUNC_ALIAS_MEMFUNC        SYM_FUNC_ALIAS
+#endif
+
 /* SYM_TYPED_FUNC_START -- use for indirectly called globals, w/ CFI type */
 #define SYM_TYPED_FUNC_START(name)                             \
        SYM_TYPED_START(name, SYM_L_GLOBAL, SYM_F_ALIGN)        \
index 416901d406f8a09d98580315759782a6c559d68e..8dac45a2c7fcf236708272ac7379d3d706c13493 100644 (file)
@@ -186,8 +186,7 @@ do {                                                \
 #else
 #define deactivate_mm(tsk, mm)                 \
 do {                                           \
-       if (!tsk->vfork_done)                   \
-               shstk_free(tsk);                \
+       shstk_free(tsk);                        \
        load_gs_index(0);                       \
        loadsegment(fs, 0);                     \
 } while (0)
index 4acbcddddc29f21fc9f21117b653c842430d943c..772d03487520e595ba458ae9032f8a0a2dc00101 100644 (file)
@@ -9,13 +9,6 @@ struct paravirt_patch_site {
        u8 type;                /* type of this instruction */
        u8 len;                 /* length of original instruction */
 };
-
-/* Lazy mode for batching updates / context switch */
-enum paravirt_lazy_mode {
-       PARAVIRT_LAZY_NONE,
-       PARAVIRT_LAZY_MMU,
-       PARAVIRT_LAZY_CPU,
-};
 #endif
 
 #ifdef CONFIG_PARAVIRT
@@ -549,14 +542,6 @@ int paravirt_disable_iospace(void);
        __PVOP_VCALL(op, PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2),    \
                     PVOP_CALL_ARG3(arg3), PVOP_CALL_ARG4(arg4))
 
-enum paravirt_lazy_mode paravirt_get_lazy_mode(void);
-void paravirt_start_context_switch(struct task_struct *prev);
-void paravirt_end_context_switch(struct task_struct *next);
-
-void paravirt_enter_lazy_mmu(void);
-void paravirt_leave_lazy_mmu(void);
-void paravirt_flush_lazy_mmu(void);
-
 void _paravirt_nop(void);
 void paravirt_BUG(void);
 unsigned long paravirt_ret0(void);
index 0086920cda061f83f2050822646bfadbc0f474bc..a3669a7774edbbb9f622f2e882b9089ce39f2202 100644 (file)
@@ -683,13 +683,11 @@ extern u16 get_llc_id(unsigned int cpu);
 #ifdef CONFIG_CPU_SUP_AMD
 extern u32 amd_get_nodes_per_socket(void);
 extern u32 amd_get_highest_perf(void);
-extern bool cpu_has_ibpb_brtype_microcode(void);
 extern void amd_clear_divider(void);
 extern void amd_check_microcode(void);
 #else
 static inline u32 amd_get_nodes_per_socket(void)       { return 0; }
 static inline u32 amd_get_highest_perf(void)           { return 0; }
-static inline bool cpu_has_ibpb_brtype_microcode(void) { return false; }
 static inline void amd_clear_divider(void)             { }
 static inline void amd_check_microcode(void)           { }
 #endif
index 5fc35f889cd1a29d86f245da3c7e1f993f3cdf4d..7048dfacc04b2413acba1054fb4412c7048b8249 100644 (file)
@@ -36,6 +36,7 @@
 extern struct shared_info *HYPERVISOR_shared_info;
 extern struct start_info *xen_start_info;
 
+#include <asm/bug.h>
 #include <asm/processor.h>
 
 #define XEN_SIGNATURE "XenVMMXenVMM"
@@ -63,4 +64,40 @@ void __init xen_pvh_init(struct boot_params *boot_params);
 void __init mem_map_via_hcall(struct boot_params *boot_params_p);
 #endif
 
+/* Lazy mode for batching updates / context switch */
+enum xen_lazy_mode {
+       XEN_LAZY_NONE,
+       XEN_LAZY_MMU,
+       XEN_LAZY_CPU,
+};
+
+DECLARE_PER_CPU(enum xen_lazy_mode, xen_lazy_mode);
+DECLARE_PER_CPU(unsigned int, xen_lazy_nesting);
+
+static inline void enter_lazy(enum xen_lazy_mode mode)
+{
+       enum xen_lazy_mode old_mode = this_cpu_read(xen_lazy_mode);
+
+       if (mode == old_mode) {
+               this_cpu_inc(xen_lazy_nesting);
+               return;
+       }
+
+       BUG_ON(old_mode != XEN_LAZY_NONE);
+
+       this_cpu_write(xen_lazy_mode, mode);
+}
+
+static inline void leave_lazy(enum xen_lazy_mode mode)
+{
+       BUG_ON(this_cpu_read(xen_lazy_mode) != mode);
+
+       if (this_cpu_read(xen_lazy_nesting) == 0)
+               this_cpu_write(xen_lazy_mode, XEN_LAZY_NONE);
+       else
+               this_cpu_dec(xen_lazy_nesting);
+}
+
+enum xen_lazy_mode xen_get_lazy_mode(void);
+
 #endif /* _ASM_X86_XEN_HYPERVISOR_H */
index a5ead6a6d233b2ef4223d5ba54579a69f3042f6f..517ee01503be1e9fab72b3ecd80adfca7ce99d8a 100644 (file)
@@ -720,13 +720,8 @@ void __init_or_module noinline apply_returns(s32 *start, s32 *end)
 {
        s32 *s;
 
-       /*
-        * Do not patch out the default return thunks if those needed are the
-        * ones generated by the compiler.
-        */
-       if (cpu_feature_enabled(X86_FEATURE_RETHUNK) &&
-           (x86_return_thunk == __x86_return_thunk))
-               return;
+       if (cpu_feature_enabled(X86_FEATURE_RETHUNK))
+               static_call_force_reinit();
 
        for (s = start; s < end; s++) {
                void *dest = NULL, *addr = (void *)s + *s;
index d9f5d7492f8371df1004159297a4b4ad48c78e63..205cee5676298fb6b04c592e02d9a7585a9a6072 100644 (file)
@@ -1533,7 +1533,7 @@ static void __init build_socket_tables(void)
 {
        struct uv_gam_range_entry *gre = uv_gre_table;
        int nums, numn, nump;
-       int cpu, i, lnid;
+       int i, lnid, apicid;
        int minsock = _min_socket;
        int maxsock = _max_socket;
        int minpnode = _min_pnode;
@@ -1584,15 +1584,14 @@ static void __init build_socket_tables(void)
 
        /* Set socket -> node values: */
        lnid = NUMA_NO_NODE;
-       for_each_possible_cpu(cpu) {
-               int nid = cpu_to_node(cpu);
-               int apicid, sockid;
+       for (apicid = 0; apicid < ARRAY_SIZE(__apicid_to_node); apicid++) {
+               int nid = __apicid_to_node[apicid];
+               int sockid;
 
-               if (lnid == nid)
+               if ((nid == NUMA_NO_NODE) || (lnid == nid))
                        continue;
                lnid = nid;
 
-               apicid = per_cpu(x86_cpu_to_apicid, cpu);
                sockid = apicid >> uv_cpuid.socketid_shift;
 
                if (_socket_to_node[sockid - minsock] == SOCK_EMPTY)
index c06bfc086565dff236c72c0ab9758c3239c63bcc..faa9f22998488758c5513091b491e99932cd6980 100644 (file)
@@ -272,7 +272,6 @@ void __init callthunks_patch_builtin_calls(void)
        pr_info("Setting up call depth tracking\n");
        mutex_lock(&text_mutex);
        callthunks_setup(&cs, &builtin_coretext);
-       static_call_force_reinit();
        thunks_initialized = true;
        mutex_unlock(&text_mutex);
 }
index dd8379d844452b17dceaa37ff2c6c45e65e1f0e1..03ef962a6992db0281697ea0d02b89e97f677dd5 100644 (file)
@@ -766,6 +766,15 @@ static void early_init_amd(struct cpuinfo_x86 *c)
 
        if (cpu_has(c, X86_FEATURE_TOPOEXT))
                smp_num_siblings = ((cpuid_ebx(0x8000001e) >> 8) & 0xff) + 1;
+
+       if (!cpu_has(c, X86_FEATURE_HYPERVISOR) && !cpu_has(c, X86_FEATURE_IBPB_BRTYPE)) {
+               if (c->x86 == 0x17 && boot_cpu_has(X86_FEATURE_AMD_IBPB))
+                       setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE);
+               else if (c->x86 >= 0x19 && !wrmsrl_safe(MSR_IA32_PRED_CMD, PRED_CMD_SBPB)) {
+                       setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE);
+                       setup_force_cpu_cap(X86_FEATURE_SBPB);
+               }
+       }
 }
 
 static void init_amd_k8(struct cpuinfo_x86 *c)
@@ -1301,25 +1310,6 @@ void amd_check_microcode(void)
        on_each_cpu(zenbleed_check_cpu, NULL, 1);
 }
 
-bool cpu_has_ibpb_brtype_microcode(void)
-{
-       switch (boot_cpu_data.x86) {
-       /* Zen1/2 IBPB flushes branch type predictions too. */
-       case 0x17:
-               return boot_cpu_has(X86_FEATURE_AMD_IBPB);
-       case 0x19:
-               /* Poke the MSR bit on Zen3/4 to check its presence. */
-               if (!wrmsrl_safe(MSR_IA32_PRED_CMD, PRED_CMD_SBPB)) {
-                       setup_force_cpu_cap(X86_FEATURE_SBPB);
-                       return true;
-               } else {
-                       return false;
-               }
-       default:
-               return false;
-       }
-}
-
 /*
  * Issue a DIV 0/1 insn to clear any division data from previous DIV
  * operations.
index f081d26616ac1ce9aebf720ce3430bece3a02025..10499bcd4e39624827e9641df81eda074bc3cfdc 100644 (file)
@@ -2404,26 +2404,15 @@ early_param("spec_rstack_overflow", srso_parse_cmdline);
 
 static void __init srso_select_mitigation(void)
 {
-       bool has_microcode;
+       bool has_microcode = boot_cpu_has(X86_FEATURE_IBPB_BRTYPE);
 
        if (!boot_cpu_has_bug(X86_BUG_SRSO) || cpu_mitigations_off())
                goto pred_cmd;
 
-       /*
-        * The first check is for the kernel running as a guest in order
-        * for guests to verify whether IBPB is a viable mitigation.
-        */
-       has_microcode = boot_cpu_has(X86_FEATURE_IBPB_BRTYPE) || cpu_has_ibpb_brtype_microcode();
        if (!has_microcode) {
                pr_warn("IBPB-extending microcode not applied!\n");
                pr_warn(SRSO_NOTICE);
        } else {
-               /*
-                * Enable the synthetic (even if in a real CPUID leaf)
-                * flags for guests.
-                */
-               setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE);
-
                /*
                 * Zen1/2 with SMT off aren't vulnerable after the right
                 * IBPB microcode has been applied.
@@ -2444,7 +2433,7 @@ static void __init srso_select_mitigation(void)
 
        switch (srso_cmd) {
        case SRSO_CMD_OFF:
-               return;
+               goto pred_cmd;
 
        case SRSO_CMD_MICROCODE:
                if (has_microcode) {
@@ -2717,7 +2706,7 @@ static ssize_t srso_show_state(char *buf)
 
        return sysfs_emit(buf, "%s%s\n",
                          srso_strings[srso_mitigation],
-                         (cpu_has_ibpb_brtype_microcode() ? "" : ", no microcode"));
+                         boot_cpu_has(X86_FEATURE_IBPB_BRTYPE) ? "" : ", no microcode");
 }
 
 static ssize_t gds_show_state(char *buf)
index 975f98d5eee5dcf46d0b40d63199eb21c5c39c7a..97f1436c1a20348a567ea439aeaa41881448d625 100644 (file)
@@ -143,66 +143,7 @@ int paravirt_disable_iospace(void)
        return request_resource(&ioport_resource, &reserve_ioports);
 }
 
-static DEFINE_PER_CPU(enum paravirt_lazy_mode, paravirt_lazy_mode) = PARAVIRT_LAZY_NONE;
-
-static inline void enter_lazy(enum paravirt_lazy_mode mode)
-{
-       BUG_ON(this_cpu_read(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE);
-
-       this_cpu_write(paravirt_lazy_mode, mode);
-}
-
-static void leave_lazy(enum paravirt_lazy_mode mode)
-{
-       BUG_ON(this_cpu_read(paravirt_lazy_mode) != mode);
-
-       this_cpu_write(paravirt_lazy_mode, PARAVIRT_LAZY_NONE);
-}
-
-void paravirt_enter_lazy_mmu(void)
-{
-       enter_lazy(PARAVIRT_LAZY_MMU);
-}
-
-void paravirt_leave_lazy_mmu(void)
-{
-       leave_lazy(PARAVIRT_LAZY_MMU);
-}
-
-void paravirt_flush_lazy_mmu(void)
-{
-       preempt_disable();
-
-       if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
-               arch_leave_lazy_mmu_mode();
-               arch_enter_lazy_mmu_mode();
-       }
-
-       preempt_enable();
-}
-
 #ifdef CONFIG_PARAVIRT_XXL
-void paravirt_start_context_switch(struct task_struct *prev)
-{
-       BUG_ON(preemptible());
-
-       if (this_cpu_read(paravirt_lazy_mode) == PARAVIRT_LAZY_MMU) {
-               arch_leave_lazy_mmu_mode();
-               set_ti_thread_flag(task_thread_info(prev), TIF_LAZY_MMU_UPDATES);
-       }
-       enter_lazy(PARAVIRT_LAZY_CPU);
-}
-
-void paravirt_end_context_switch(struct task_struct *next)
-{
-       BUG_ON(preemptible());
-
-       leave_lazy(PARAVIRT_LAZY_CPU);
-
-       if (test_and_clear_ti_thread_flag(task_thread_info(next), TIF_LAZY_MMU_UPDATES))
-               arch_enter_lazy_mmu_mode();
-}
-
 static noinstr void pv_native_write_cr2(unsigned long val)
 {
        native_write_cr2(val);
@@ -229,14 +170,6 @@ static noinstr void pv_native_safe_halt(void)
 }
 #endif
 
-enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
-{
-       if (in_interrupt())
-               return PARAVIRT_LAZY_NONE;
-
-       return this_cpu_read(paravirt_lazy_mode);
-}
-
 struct pv_info pv_info = {
        .name = "bare hardware",
 #ifdef CONFIG_PARAVIRT_XXL
index 9f0909142a0ae38e322b31d7e124589e408f21a0..b6f4e8399fca20ddae6b147fa4209a97b188ec25 100644 (file)
@@ -257,13 +257,6 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
        if (!ret && unlikely(test_tsk_thread_flag(current, TIF_IO_BITMAP)))
                io_bitmap_share(p);
 
-       /*
-        * If copy_thread() if failing, don't leak the shadow stack possibly
-        * allocated in shstk_alloc_thread_stack() above.
-        */
-       if (ret)
-               shstk_free(p);
-
        return ret;
 }
 
index b9145a63da77d83586eb6fe608bfa0ff617ddd9b..b098b1fa2470816a35d7784d93c0e7ae0fc83f6d 100644 (file)
@@ -358,15 +358,11 @@ static void __init add_early_ima_buffer(u64 phys_addr)
 #if defined(CONFIG_HAVE_IMA_KEXEC) && !defined(CONFIG_OF_FLATTREE)
 int __init ima_free_kexec_buffer(void)
 {
-       int rc;
-
        if (!ima_kexec_buffer_size)
                return -ENOENT;
 
-       rc = memblock_phys_free(ima_kexec_buffer_phys,
-                               ima_kexec_buffer_size);
-       if (rc)
-               return rc;
+       memblock_free_late(ima_kexec_buffer_phys,
+                          ima_kexec_buffer_size);
 
        ima_kexec_buffer_phys = 0;
        ima_kexec_buffer_size = 0;
index fd689921a1dbad3c4036132d977d9b4bee438b98..59e15dd8d0f86665ef0949b1c7072b9d25205c5e 100644 (file)
@@ -205,10 +205,21 @@ unsigned long shstk_alloc_thread_stack(struct task_struct *tsk, unsigned long cl
                return 0;
 
        /*
-        * For CLONE_VM, except vfork, the child needs a separate shadow
+        * For CLONE_VFORK the child will share the parents shadow stack.
+        * Make sure to clear the internal tracking of the thread shadow
+        * stack so the freeing logic run for child knows to leave it alone.
+        */
+       if (clone_flags & CLONE_VFORK) {
+               shstk->base = 0;
+               shstk->size = 0;
+               return 0;
+       }
+
+       /*
+        * For !CLONE_VM the child will use a copy of the parents shadow
         * stack.
         */
-       if ((clone_flags & (CLONE_VFORK | CLONE_VM)) != CLONE_VM)
+       if (!(clone_flags & CLONE_VM))
                return 0;
 
        size = adjust_shstk_size(stack_size);
@@ -408,7 +419,25 @@ void shstk_free(struct task_struct *tsk)
        if (!tsk->mm || tsk->mm != current->mm)
                return;
 
+       /*
+        * If shstk->base is NULL, then this task is not managing its
+        * own shadow stack (CLONE_VFORK). So skip freeing it.
+        */
+       if (!shstk->base)
+               return;
+
+       /*
+        * shstk->base is NULL for CLONE_VFORK child tasks, and so is
+        * normal. But size = 0 on a shstk->base is not normal and
+        * indicated an attempt to free the thread shadow stack twice.
+        * Warn about it.
+        */
+       if (WARN_ON(!shstk->size))
+               return;
+
        unmap_shadow_stack(shstk->base, shstk->size);
+
+       shstk->size = 0;
 }
 
 static int wrss_control(bool enable)
index 4e45ff44aa07db38e6d765605e6f12b80fe3f08d..48e0406187314f1342f6dcffa4552edf9f0291ec 100644 (file)
@@ -579,7 +579,6 @@ static bool match_llc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
 }
 
 
-#if defined(CONFIG_SCHED_SMT) || defined(CONFIG_SCHED_CLUSTER) || defined(CONFIG_SCHED_MC)
 static inline int x86_sched_itmt_flags(void)
 {
        return sysctl_sched_itmt_enabled ? SD_ASYM_PACKING : 0;
@@ -603,7 +602,14 @@ static int x86_cluster_flags(void)
        return cpu_cluster_flags() | x86_sched_itmt_flags();
 }
 #endif
-#endif
+
+static int x86_die_flags(void)
+{
+       if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU))
+              return x86_sched_itmt_flags();
+
+       return 0;
+}
 
 /*
  * Set if a package/die has multiple NUMA nodes inside.
@@ -640,7 +646,7 @@ static void __init build_sched_topology(void)
         */
        if (!x86_has_numa_in_package) {
                x86_topology[i++] = (struct sched_domain_topology_level){
-                       cpu_cpu_mask, SD_INIT_NAME(DIE)
+                       cpu_cpu_mask, x86_die_flags, SD_INIT_NAME(DIE)
                };
        }
 
index e1d011c67cc6de3785fb76f87f11ce727ef95593..f7901cb4d2fa4b67a4dae93648a169fd2931585b 100644 (file)
@@ -6167,20 +6167,15 @@ static bool kvm_has_zapped_obsolete_pages(struct kvm *kvm)
        return unlikely(!list_empty_careful(&kvm->arch.zapped_obsolete_pages));
 }
 
-int kvm_mmu_init_vm(struct kvm *kvm)
+void kvm_mmu_init_vm(struct kvm *kvm)
 {
-       int r;
-
        INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
        INIT_LIST_HEAD(&kvm->arch.zapped_obsolete_pages);
        INIT_LIST_HEAD(&kvm->arch.possible_nx_huge_pages);
        spin_lock_init(&kvm->arch.mmu_unsync_pages_lock);
 
-       if (tdp_mmu_enabled) {
-               r = kvm_mmu_init_tdp_mmu(kvm);
-               if (r < 0)
-                       return r;
-       }
+       if (tdp_mmu_enabled)
+               kvm_mmu_init_tdp_mmu(kvm);
 
        kvm->arch.split_page_header_cache.kmem_cache = mmu_page_header_cache;
        kvm->arch.split_page_header_cache.gfp_zero = __GFP_ZERO;
@@ -6189,8 +6184,6 @@ int kvm_mmu_init_vm(struct kvm *kvm)
 
        kvm->arch.split_desc_cache.kmem_cache = pte_list_desc_cache;
        kvm->arch.split_desc_cache.gfp_zero = __GFP_ZERO;
-
-       return 0;
 }
 
 static void mmu_free_vm_memory_caches(struct kvm *kvm)
@@ -6246,7 +6239,6 @@ static bool kvm_rmap_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_e
 void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end)
 {
        bool flush;
-       int i;
 
        if (WARN_ON_ONCE(gfn_end <= gfn_start))
                return;
@@ -6257,11 +6249,8 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end)
 
        flush = kvm_rmap_zap_gfn_range(kvm, gfn_start, gfn_end);
 
-       if (tdp_mmu_enabled) {
-               for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
-                       flush = kvm_tdp_mmu_zap_leafs(kvm, i, gfn_start,
-                                                     gfn_end, true, flush);
-       }
+       if (tdp_mmu_enabled)
+               flush = kvm_tdp_mmu_zap_leafs(kvm, gfn_start, gfn_end, flush);
 
        if (flush)
                kvm_flush_remote_tlbs_range(kvm, gfn_start, gfn_end - gfn_start);
index b102014e2c605bdffec00bec87c500ea507ce29c..decc1f1536694f31529f3d8c2c7cf67d1185a8c0 100644 (file)
@@ -58,7 +58,12 @@ struct kvm_mmu_page {
 
        bool tdp_mmu_page;
        bool unsync;
-       u8 mmu_valid_gen;
+       union {
+               u8 mmu_valid_gen;
+
+               /* Only accessed under slots_lock.  */
+               bool tdp_mmu_scheduled_root_to_zap;
+       };
 
         /*
          * The shadow page can't be replaced by an equivalent huge page
@@ -100,13 +105,7 @@ struct kvm_mmu_page {
                struct kvm_rmap_head parent_ptes; /* rmap pointers to parent sptes */
                tdp_ptep_t ptep;
        };
-       union {
-               DECLARE_BITMAP(unsync_child_bitmap, 512);
-               struct {
-                       struct work_struct tdp_mmu_async_work;
-                       void *tdp_mmu_async_data;
-               };
-       };
+       DECLARE_BITMAP(unsync_child_bitmap, 512);
 
        /*
         * Tracks shadow pages that, if zapped, would allow KVM to create an NX
index 6c63f2d1675f9d60885f9baa1176f5e6550bf8f3..6cd4dd631a2fac815be473c62333c940a074c925 100644 (file)
 #include <trace/events/kvm.h>
 
 /* Initializes the TDP MMU for the VM, if enabled. */
-int kvm_mmu_init_tdp_mmu(struct kvm *kvm)
+void kvm_mmu_init_tdp_mmu(struct kvm *kvm)
 {
-       struct workqueue_struct *wq;
-
-       wq = alloc_workqueue("kvm", WQ_UNBOUND|WQ_MEM_RECLAIM|WQ_CPU_INTENSIVE, 0);
-       if (!wq)
-               return -ENOMEM;
-
        INIT_LIST_HEAD(&kvm->arch.tdp_mmu_roots);
        spin_lock_init(&kvm->arch.tdp_mmu_pages_lock);
-       kvm->arch.tdp_mmu_zap_wq = wq;
-       return 1;
 }
 
 /* Arbitrarily returns true so that this may be used in if statements. */
@@ -46,20 +38,15 @@ void kvm_mmu_uninit_tdp_mmu(struct kvm *kvm)
         * ultimately frees all roots.
         */
        kvm_tdp_mmu_invalidate_all_roots(kvm);
-
-       /*
-        * Destroying a workqueue also first flushes the workqueue, i.e. no
-        * need to invoke kvm_tdp_mmu_zap_invalidated_roots().
-        */
-       destroy_workqueue(kvm->arch.tdp_mmu_zap_wq);
+       kvm_tdp_mmu_zap_invalidated_roots(kvm);
 
        WARN_ON(atomic64_read(&kvm->arch.tdp_mmu_pages));
        WARN_ON(!list_empty(&kvm->arch.tdp_mmu_roots));
 
        /*
         * Ensure that all the outstanding RCU callbacks to free shadow pages
-        * can run before the VM is torn down.  Work items on tdp_mmu_zap_wq
-        * can call kvm_tdp_mmu_put_root and create new callbacks.
+        * can run before the VM is torn down.  Putting the last reference to
+        * zapped roots will create new callbacks.
         */
        rcu_barrier();
 }
@@ -86,46 +73,6 @@ static void tdp_mmu_free_sp_rcu_callback(struct rcu_head *head)
        tdp_mmu_free_sp(sp);
 }
 
-static void tdp_mmu_zap_root(struct kvm *kvm, struct kvm_mmu_page *root,
-                            bool shared);
-
-static void tdp_mmu_zap_root_work(struct work_struct *work)
-{
-       struct kvm_mmu_page *root = container_of(work, struct kvm_mmu_page,
-                                                tdp_mmu_async_work);
-       struct kvm *kvm = root->tdp_mmu_async_data;
-
-       read_lock(&kvm->mmu_lock);
-
-       /*
-        * A TLB flush is not necessary as KVM performs a local TLB flush when
-        * allocating a new root (see kvm_mmu_load()), and when migrating vCPU
-        * to a different pCPU.  Note, the local TLB flush on reuse also
-        * invalidates any paging-structure-cache entries, i.e. TLB entries for
-        * intermediate paging structures, that may be zapped, as such entries
-        * are associated with the ASID on both VMX and SVM.
-        */
-       tdp_mmu_zap_root(kvm, root, true);
-
-       /*
-        * Drop the refcount using kvm_tdp_mmu_put_root() to test its logic for
-        * avoiding an infinite loop.  By design, the root is reachable while
-        * it's being asynchronously zapped, thus a different task can put its
-        * last reference, i.e. flowing through kvm_tdp_mmu_put_root() for an
-        * asynchronously zapped root is unavoidable.
-        */
-       kvm_tdp_mmu_put_root(kvm, root, true);
-
-       read_unlock(&kvm->mmu_lock);
-}
-
-static void tdp_mmu_schedule_zap_root(struct kvm *kvm, struct kvm_mmu_page *root)
-{
-       root->tdp_mmu_async_data = kvm;
-       INIT_WORK(&root->tdp_mmu_async_work, tdp_mmu_zap_root_work);
-       queue_work(kvm->arch.tdp_mmu_zap_wq, &root->tdp_mmu_async_work);
-}
-
 void kvm_tdp_mmu_put_root(struct kvm *kvm, struct kvm_mmu_page *root,
                          bool shared)
 {
@@ -211,8 +158,12 @@ static struct kvm_mmu_page *tdp_mmu_next_root(struct kvm *kvm,
 #define for_each_valid_tdp_mmu_root_yield_safe(_kvm, _root, _as_id, _shared)   \
        __for_each_tdp_mmu_root_yield_safe(_kvm, _root, _as_id, _shared, true)
 
-#define for_each_tdp_mmu_root_yield_safe(_kvm, _root, _as_id)                  \
-       __for_each_tdp_mmu_root_yield_safe(_kvm, _root, _as_id, false, false)
+#define for_each_tdp_mmu_root_yield_safe(_kvm, _root, _shared)                 \
+       for (_root = tdp_mmu_next_root(_kvm, NULL, _shared, false);             \
+            _root;                                                             \
+            _root = tdp_mmu_next_root(_kvm, _root, _shared, false))            \
+               if (!kvm_lockdep_assert_mmu_lock_held(_kvm, _shared)) {         \
+               } else
 
 /*
  * Iterate over all TDP MMU roots.  Requires that mmu_lock be held for write,
@@ -292,7 +243,7 @@ hpa_t kvm_tdp_mmu_get_vcpu_root_hpa(struct kvm_vcpu *vcpu)
         * by a memslot update or by the destruction of the VM.  Initialize the
         * refcount to two; one reference for the vCPU, and one reference for
         * the TDP MMU itself, which is held until the root is invalidated and
-        * is ultimately put by tdp_mmu_zap_root_work().
+        * is ultimately put by kvm_tdp_mmu_zap_invalidated_roots().
         */
        refcount_set(&root->tdp_mmu_root_count, 2);
 
@@ -877,13 +828,12 @@ static bool tdp_mmu_zap_leafs(struct kvm *kvm, struct kvm_mmu_page *root,
  * true if a TLB flush is needed before releasing the MMU lock, i.e. if one or
  * more SPTEs were zapped since the MMU lock was last acquired.
  */
-bool kvm_tdp_mmu_zap_leafs(struct kvm *kvm, int as_id, gfn_t start, gfn_t end,
-                          bool can_yield, bool flush)
+bool kvm_tdp_mmu_zap_leafs(struct kvm *kvm, gfn_t start, gfn_t end, bool flush)
 {
        struct kvm_mmu_page *root;
 
-       for_each_tdp_mmu_root_yield_safe(kvm, root, as_id)
-               flush = tdp_mmu_zap_leafs(kvm, root, start, end, can_yield, flush);
+       for_each_tdp_mmu_root_yield_safe(kvm, root, false)
+               flush = tdp_mmu_zap_leafs(kvm, root, start, end, true, flush);
 
        return flush;
 }
@@ -891,7 +841,6 @@ bool kvm_tdp_mmu_zap_leafs(struct kvm *kvm, int as_id, gfn_t start, gfn_t end,
 void kvm_tdp_mmu_zap_all(struct kvm *kvm)
 {
        struct kvm_mmu_page *root;
-       int i;
 
        /*
         * Zap all roots, including invalid roots, as all SPTEs must be dropped
@@ -905,10 +854,8 @@ void kvm_tdp_mmu_zap_all(struct kvm *kvm)
         * is being destroyed or the userspace VMM has exited.  In both cases,
         * KVM_RUN is unreachable, i.e. no vCPUs will ever service the request.
         */
-       for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) {
-               for_each_tdp_mmu_root_yield_safe(kvm, root, i)
-                       tdp_mmu_zap_root(kvm, root, false);
-       }
+       for_each_tdp_mmu_root_yield_safe(kvm, root, false)
+               tdp_mmu_zap_root(kvm, root, false);
 }
 
 /*
@@ -917,18 +864,47 @@ void kvm_tdp_mmu_zap_all(struct kvm *kvm)
  */
 void kvm_tdp_mmu_zap_invalidated_roots(struct kvm *kvm)
 {
-       flush_workqueue(kvm->arch.tdp_mmu_zap_wq);
+       struct kvm_mmu_page *root;
+
+       read_lock(&kvm->mmu_lock);
+
+       for_each_tdp_mmu_root_yield_safe(kvm, root, true) {
+               if (!root->tdp_mmu_scheduled_root_to_zap)
+                       continue;
+
+               root->tdp_mmu_scheduled_root_to_zap = false;
+               KVM_BUG_ON(!root->role.invalid, kvm);
+
+               /*
+                * A TLB flush is not necessary as KVM performs a local TLB
+                * flush when allocating a new root (see kvm_mmu_load()), and
+                * when migrating a vCPU to a different pCPU.  Note, the local
+                * TLB flush on reuse also invalidates paging-structure-cache
+                * entries, i.e. TLB entries for intermediate paging structures,
+                * that may be zapped, as such entries are associated with the
+                * ASID on both VMX and SVM.
+                */
+               tdp_mmu_zap_root(kvm, root, true);
+
+               /*
+                * The referenced needs to be put *after* zapping the root, as
+                * the root must be reachable by mmu_notifiers while it's being
+                * zapped
+                */
+               kvm_tdp_mmu_put_root(kvm, root, true);
+       }
+
+       read_unlock(&kvm->mmu_lock);
 }
 
 /*
  * Mark each TDP MMU root as invalid to prevent vCPUs from reusing a root that
  * is about to be zapped, e.g. in response to a memslots update.  The actual
- * zapping is performed asynchronously.  Using a separate workqueue makes it
- * easy to ensure that the destruction is performed before the "fast zap"
- * completes, without keeping a separate list of invalidated roots; the list is
- * effectively the list of work items in the workqueue.
+ * zapping is done separately so that it happens with mmu_lock with read,
+ * whereas invalidating roots must be done with mmu_lock held for write (unless
+ * the VM is being destroyed).
  *
- * Note, the asynchronous worker is gifted the TDP MMU's reference.
+ * Note, kvm_tdp_mmu_zap_invalidated_roots() is gifted the TDP MMU's reference.
  * See kvm_tdp_mmu_get_vcpu_root_hpa().
  */
 void kvm_tdp_mmu_invalidate_all_roots(struct kvm *kvm)
@@ -953,19 +929,20 @@ void kvm_tdp_mmu_invalidate_all_roots(struct kvm *kvm)
        /*
         * As above, mmu_lock isn't held when destroying the VM!  There can't
         * be other references to @kvm, i.e. nothing else can invalidate roots
-        * or be consuming roots, but walking the list of roots does need to be
-        * guarded against roots being deleted by the asynchronous zap worker.
+        * or get/put references to roots.
         */
-       rcu_read_lock();
-
-       list_for_each_entry_rcu(root, &kvm->arch.tdp_mmu_roots, link) {
+       list_for_each_entry(root, &kvm->arch.tdp_mmu_roots, link) {
+               /*
+                * Note, invalid roots can outlive a memslot update!  Invalid
+                * roots must be *zapped* before the memslot update completes,
+                * but a different task can acquire a reference and keep the
+                * root alive after its been zapped.
+                */
                if (!root->role.invalid) {
+                       root->tdp_mmu_scheduled_root_to_zap = true;
                        root->role.invalid = true;
-                       tdp_mmu_schedule_zap_root(kvm, root);
                }
        }
-
-       rcu_read_unlock();
 }
 
 /*
@@ -1146,8 +1123,13 @@ retry:
 bool kvm_tdp_mmu_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range,
                                 bool flush)
 {
-       return kvm_tdp_mmu_zap_leafs(kvm, range->slot->as_id, range->start,
-                                    range->end, range->may_block, flush);
+       struct kvm_mmu_page *root;
+
+       __for_each_tdp_mmu_root_yield_safe(kvm, root, range->slot->as_id, false, false)
+               flush = tdp_mmu_zap_leafs(kvm, root, range->start, range->end,
+                                         range->may_block, flush);
+
+       return flush;
 }
 
 typedef bool (*tdp_handler_t)(struct kvm *kvm, struct tdp_iter *iter,
index 0a63b1afabd3cceef4e6e2ecb8ca5b3893becb5f..733a3aef3a96eaa32964e8fc042c26fae0a0ee9c 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "spte.h"
 
-int kvm_mmu_init_tdp_mmu(struct kvm *kvm);
+void kvm_mmu_init_tdp_mmu(struct kvm *kvm);
 void kvm_mmu_uninit_tdp_mmu(struct kvm *kvm);
 
 hpa_t kvm_tdp_mmu_get_vcpu_root_hpa(struct kvm_vcpu *vcpu);
@@ -20,8 +20,7 @@ __must_check static inline bool kvm_tdp_mmu_get_root(struct kvm_mmu_page *root)
 void kvm_tdp_mmu_put_root(struct kvm *kvm, struct kvm_mmu_page *root,
                          bool shared);
 
-bool kvm_tdp_mmu_zap_leafs(struct kvm *kvm, int as_id, gfn_t start,
-                                gfn_t end, bool can_yield, bool flush);
+bool kvm_tdp_mmu_zap_leafs(struct kvm *kvm, gfn_t start, gfn_t end, bool flush);
 bool kvm_tdp_mmu_zap_sp(struct kvm *kvm, struct kvm_mmu_page *sp);
 void kvm_tdp_mmu_zap_all(struct kvm *kvm);
 void kvm_tdp_mmu_invalidate_all_roots(struct kvm *kvm);
index b9a0a939d59f3826edb3d6839413e5dfd7ae66b8..4900c078045acc1bf437859f46e9acbe9c66b0b4 100644 (file)
@@ -2962,6 +2962,32 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in)
                                    count, in);
 }
 
+static void sev_es_vcpu_after_set_cpuid(struct vcpu_svm *svm)
+{
+       struct kvm_vcpu *vcpu = &svm->vcpu;
+
+       if (boot_cpu_has(X86_FEATURE_V_TSC_AUX)) {
+               bool v_tsc_aux = guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP) ||
+                                guest_cpuid_has(vcpu, X86_FEATURE_RDPID);
+
+               set_msr_interception(vcpu, svm->msrpm, MSR_TSC_AUX, v_tsc_aux, v_tsc_aux);
+       }
+}
+
+void sev_vcpu_after_set_cpuid(struct vcpu_svm *svm)
+{
+       struct kvm_vcpu *vcpu = &svm->vcpu;
+       struct kvm_cpuid_entry2 *best;
+
+       /* For sev guests, the memory encryption bit is not reserved in CR3.  */
+       best = kvm_find_cpuid_entry(vcpu, 0x8000001F);
+       if (best)
+               vcpu->arch.reserved_gpa_bits &= ~(1UL << (best->ebx & 0x3f));
+
+       if (sev_es_guest(svm->vcpu.kvm))
+               sev_es_vcpu_after_set_cpuid(svm);
+}
+
 static void sev_es_init_vmcb(struct vcpu_svm *svm)
 {
        struct vmcb *vmcb = svm->vmcb01.ptr;
@@ -3024,14 +3050,6 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm)
        set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTBRANCHTOIP, 1, 1);
        set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTINTFROMIP, 1, 1);
        set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTINTTOIP, 1, 1);
-
-       if (boot_cpu_has(X86_FEATURE_V_TSC_AUX) &&
-           (guest_cpuid_has(&svm->vcpu, X86_FEATURE_RDTSCP) ||
-            guest_cpuid_has(&svm->vcpu, X86_FEATURE_RDPID))) {
-               set_msr_interception(vcpu, svm->msrpm, MSR_TSC_AUX, 1, 1);
-               if (guest_cpuid_has(&svm->vcpu, X86_FEATURE_RDTSCP))
-                       svm_clr_intercept(svm, INTERCEPT_RDTSCP);
-       }
 }
 
 void sev_init_vmcb(struct vcpu_svm *svm)
index f283eb47f6acec7d34453c2047536bfaa14b66c5..9507df93f410a631b1b06acd9937bea881e7b5c9 100644 (file)
@@ -683,6 +683,21 @@ static int svm_hardware_enable(void)
 
        amd_pmu_enable_virt();
 
+       /*
+        * If TSC_AUX virtualization is supported, TSC_AUX becomes a swap type
+        * "B" field (see sev_es_prepare_switch_to_guest()) for SEV-ES guests.
+        * Since Linux does not change the value of TSC_AUX once set, prime the
+        * TSC_AUX field now to avoid a RDMSR on every vCPU run.
+        */
+       if (boot_cpu_has(X86_FEATURE_V_TSC_AUX)) {
+               struct sev_es_save_area *hostsa;
+               u32 msr_hi;
+
+               hostsa = (struct sev_es_save_area *)(page_address(sd->save_area) + 0x400);
+
+               rdmsr(MSR_TSC_AUX, hostsa->tsc_aux, msr_hi);
+       }
+
        return 0;
 }
 
@@ -1532,7 +1547,14 @@ static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
        if (tsc_scaling)
                __svm_write_tsc_multiplier(vcpu->arch.tsc_scaling_ratio);
 
-       if (likely(tsc_aux_uret_slot >= 0))
+       /*
+        * TSC_AUX is always virtualized for SEV-ES guests when the feature is
+        * available. The user return MSR support is not required in this case
+        * because TSC_AUX is restored on #VMEXIT from the host save area
+        * (which has been initialized in svm_hardware_enable()).
+        */
+       if (likely(tsc_aux_uret_slot >= 0) &&
+           (!boot_cpu_has(X86_FEATURE_V_TSC_AUX) || !sev_es_guest(vcpu->kvm)))
                kvm_set_user_return_msr(tsc_aux_uret_slot, svm->tsc_aux, -1ull);
 
        svm->guest_state_loaded = true;
@@ -3086,6 +3108,16 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
                svm->sysenter_esp_hi = guest_cpuid_is_intel(vcpu) ? (data >> 32) : 0;
                break;
        case MSR_TSC_AUX:
+               /*
+                * TSC_AUX is always virtualized for SEV-ES guests when the
+                * feature is available. The user return MSR support is not
+                * required in this case because TSC_AUX is restored on #VMEXIT
+                * from the host save area (which has been initialized in
+                * svm_hardware_enable()).
+                */
+               if (boot_cpu_has(X86_FEATURE_V_TSC_AUX) && sev_es_guest(vcpu->kvm))
+                       break;
+
                /*
                 * TSC_AUX is usually changed only during boot and never read
                 * directly.  Intercept TSC_AUX instead of exposing it to the
@@ -4284,7 +4316,6 @@ static bool svm_has_emulated_msr(struct kvm *kvm, u32 index)
 static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
-       struct kvm_cpuid_entry2 *best;
 
        /*
         * SVM doesn't provide a way to disable just XSAVES in the guest, KVM
@@ -4328,12 +4359,8 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
                set_msr_interception(vcpu, svm->msrpm, MSR_IA32_FLUSH_CMD, 0,
                                     !!guest_cpuid_has(vcpu, X86_FEATURE_FLUSH_L1D));
 
-       /* For sev guests, the memory encryption bit is not reserved in CR3.  */
-       if (sev_guest(vcpu->kvm)) {
-               best = kvm_find_cpuid_entry(vcpu, 0x8000001F);
-               if (best)
-                       vcpu->arch.reserved_gpa_bits &= ~(1UL << (best->ebx & 0x3f));
-       }
+       if (sev_guest(vcpu->kvm))
+               sev_vcpu_after_set_cpuid(svm);
 
        init_vmcb_after_set_cpuid(vcpu);
 }
index f41253958357b7730b280fe17e990c91e0b23a05..be67ab7fdd104e33f1ecc960e94d23e9385acf73 100644 (file)
@@ -684,6 +684,7 @@ void __init sev_hardware_setup(void);
 void sev_hardware_unsetup(void);
 int sev_cpu_init(struct svm_cpu_data *sd);
 void sev_init_vmcb(struct vcpu_svm *svm);
+void sev_vcpu_after_set_cpuid(struct vcpu_svm *svm);
 void sev_free_vcpu(struct kvm_vcpu *vcpu);
 int sev_handle_vmgexit(struct kvm_vcpu *vcpu);
 int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in);
index 6c9c81e82e654fc41b197beaa439c90b7ab8521b..9f18b06bbda66bf411bb492fa4ab4c5fd9e90080 100644 (file)
@@ -12308,9 +12308,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        if (ret)
                goto out;
 
-       ret = kvm_mmu_init_vm(kvm);
-       if (ret)
-               goto out_page_track;
+       kvm_mmu_init_vm(kvm);
 
        ret = static_call(kvm_x86_vm_init)(kvm);
        if (ret)
@@ -12355,7 +12353,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 
 out_uninit_mmu:
        kvm_mmu_uninit_vm(kvm);
-out_page_track:
        kvm_page_track_cleanup(kvm);
 out:
        return ret;
index 8f95fb267caa7c91d066002838198106ef052199..76697df8dfd5bf912fae0c4983f269434151a834 100644 (file)
@@ -40,7 +40,7 @@ SYM_TYPED_FUNC_START(__memcpy)
 SYM_FUNC_END(__memcpy)
 EXPORT_SYMBOL(__memcpy)
 
-SYM_FUNC_ALIAS(memcpy, __memcpy)
+SYM_FUNC_ALIAS_MEMFUNC(memcpy, __memcpy)
 EXPORT_SYMBOL(memcpy)
 
 SYM_FUNC_START_LOCAL(memcpy_orig)
index 0559b206fb1109c459d4a74b50dd6226f69a8153..ccdf3a597045e4c1a8df2146d7a4afdf0376bc3a 100644 (file)
@@ -212,5 +212,5 @@ SYM_FUNC_START(__memmove)
 SYM_FUNC_END(__memmove)
 EXPORT_SYMBOL(__memmove)
 
-SYM_FUNC_ALIAS(memmove, __memmove)
+SYM_FUNC_ALIAS_MEMFUNC(memmove, __memmove)
 EXPORT_SYMBOL(memmove)
index 7c59a704c4584bf7ef3e6a50f2021c31e6f15029..3d818b849ec64b865e857a2cc0f3d99a1df9d1f1 100644 (file)
@@ -40,7 +40,7 @@ SYM_FUNC_START(__memset)
 SYM_FUNC_END(__memset)
 EXPORT_SYMBOL(__memset)
 
-SYM_FUNC_ALIAS(memset, __memset)
+SYM_FUNC_ALIAS_MEMFUNC(memset, __memset)
 EXPORT_SYMBOL(memset)
 
 SYM_FUNC_START_LOCAL(memset_orig)
index 1451e0c4ae22af2ac0721596755be825d51e32fd..235bbda6fc8230fed1b8f240b569e8951121ad19 100644 (file)
@@ -56,7 +56,6 @@ SYM_FUNC_END(__put_user_1)
 EXPORT_SYMBOL(__put_user_1)
 
 SYM_FUNC_START(__put_user_nocheck_1)
-       ENDBR
        ASM_STAC
 2:     movb %al,(%_ASM_CX)
        xor %ecx,%ecx
@@ -76,7 +75,6 @@ SYM_FUNC_END(__put_user_2)
 EXPORT_SYMBOL(__put_user_2)
 
 SYM_FUNC_START(__put_user_nocheck_2)
-       ENDBR
        ASM_STAC
 4:     movw %ax,(%_ASM_CX)
        xor %ecx,%ecx
@@ -96,7 +94,6 @@ SYM_FUNC_END(__put_user_4)
 EXPORT_SYMBOL(__put_user_4)
 
 SYM_FUNC_START(__put_user_nocheck_4)
-       ENDBR
        ASM_STAC
 6:     movl %eax,(%_ASM_CX)
        xor %ecx,%ecx
@@ -119,7 +116,6 @@ SYM_FUNC_END(__put_user_8)
 EXPORT_SYMBOL(__put_user_8)
 
 SYM_FUNC_START(__put_user_nocheck_8)
-       ENDBR
        ASM_STAC
 9:     mov %_ASM_AX,(%_ASM_CX)
 #ifdef CONFIG_X86_32
index e06a199423c0fedd79cb9a4cc4173655ecf3956c..b2cc7b4552a16630164b6af8e574eee448933ca5 100644 (file)
@@ -140,3 +140,15 @@ void __init efi_runtime_update_mappings(void)
                }
        }
 }
+
+void arch_efi_call_virt_setup(void)
+{
+       efi_fpu_begin();
+       firmware_restrict_branch_speculation_start();
+}
+
+void arch_efi_call_virt_teardown(void)
+{
+       firmware_restrict_branch_speculation_end();
+       efi_fpu_end();
+}
index 77f7ac3668cb4ac0c97d01a7dce648e01be15fbb..91d31ac422d6cde7ab5434bcd02176cbcd6b07ff 100644 (file)
@@ -474,19 +474,34 @@ void __init efi_dump_pagetable(void)
  * can not change under us.
  * It should be ensured that there are no concurrent calls to this function.
  */
-void efi_enter_mm(void)
+static void efi_enter_mm(void)
 {
        efi_prev_mm = current->active_mm;
        current->active_mm = &efi_mm;
        switch_mm(efi_prev_mm, &efi_mm, NULL);
 }
 
-void efi_leave_mm(void)
+static void efi_leave_mm(void)
 {
        current->active_mm = efi_prev_mm;
        switch_mm(&efi_mm, efi_prev_mm, NULL);
 }
 
+void arch_efi_call_virt_setup(void)
+{
+       efi_sync_low_kernel_mappings();
+       efi_fpu_begin();
+       firmware_restrict_branch_speculation_start();
+       efi_enter_mm();
+}
+
+void arch_efi_call_virt_teardown(void)
+{
+       efi_leave_mm();
+       firmware_restrict_branch_speculation_end();
+       efi_fpu_end();
+}
+
 static DEFINE_SPINLOCK(efi_runtime_lock);
 
 /*
index c2a29be35c01bb306efbd01daabb618636f6d880..08aa0f25f12a0fb92b7f9002740c50a1c0f2ad9d 100644 (file)
@@ -19,6 +19,10 @@ CFLAGS_sha256.o := -D__DISABLE_EXPORTS -D__NO_FORTIFY
 # optimization flags.
 KBUILD_CFLAGS := $(filter-out -fprofile-sample-use=% -fprofile-use=%,$(KBUILD_CFLAGS))
 
+# When LTO is enabled, llvm emits many text sections, which is not supported
+# by kexec. Remove -flto=* flags.
+KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO),$(KBUILD_CFLAGS))
+
 # When linking purgatory.ro with -r unresolved symbols are not checked,
 # also link a purgatory.chk binary without -r to check for unresolved symbols.
 PURGATORY_LDFLAGS := -e purgatory_start -z nodefaultlib
index 863d0d6b3edc47e06346c378356b412ba2358707..7250d0e0e1a98cf8490e4b83e0ac13d44979772a 100644 (file)
@@ -138,7 +138,7 @@ void __init xen_efi_init(struct boot_params *boot_params)
        if (efi_systab_xen == NULL)
                return;
 
-       strncpy((char *)&boot_params->efi_info.efi_loader_signature, "Xen",
+       strscpy((char *)&boot_params->efi_info.efi_loader_signature, "Xen",
                        sizeof(boot_params->efi_info.efi_loader_signature));
        boot_params->efi_info.efi_systab = (__u32)__pa(efi_systab_xen);
        boot_params->efi_info.efi_systab_hi = (__u32)(__pa(efi_systab_xen) >> 32);
index b8db2148c07d525a543ecdd1ed4be5da236fc81c..0337392a3121412f8afe2946f48ff03646f780fa 100644 (file)
@@ -32,7 +32,7 @@ EXPORT_SYMBOL_GPL(hypercall_page);
  * &HYPERVISOR_shared_info->vcpu_info[cpu]. See xen_hvm_init_shared_info
  * and xen_vcpu_setup for details. By default it points to share_info->vcpu_info
  * but during boot it is switched to point to xen_vcpu_info.
- * The pointer is used in __xen_evtchn_do_upcall to acknowledge pending events.
+ * The pointer is used in xen_evtchn_do_upcall to acknowledge pending events.
  */
 DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
 DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info);
index 9a192f51f1b0216dd4e0f8cb101d49f58326fbeb..3f8c34707c50014d9364f0430728446e35059d8f 100644 (file)
@@ -136,7 +136,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_xen_hvm_callback)
 
        inc_irq_stat(irq_hv_callback_count);
 
-       xen_hvm_evtchn_do_upcall();
+       xen_evtchn_do_upcall();
 
        set_irq_regs(old_regs);
 }
index 49352fad7d1de671094c98630426be11cd12e8d3..bbbfdd495ebd3ac590fd152e0504c6bedae611de 100644 (file)
@@ -101,6 +101,17 @@ struct tls_descs {
        struct desc_struct desc[3];
 };
 
+DEFINE_PER_CPU(enum xen_lazy_mode, xen_lazy_mode) = XEN_LAZY_NONE;
+DEFINE_PER_CPU(unsigned int, xen_lazy_nesting);
+
+enum xen_lazy_mode xen_get_lazy_mode(void)
+{
+       if (in_interrupt())
+               return XEN_LAZY_NONE;
+
+       return this_cpu_read(xen_lazy_mode);
+}
+
 /*
  * Updating the 3 TLS descriptors in the GDT on every task switch is
  * surprisingly expensive so we avoid updating them if they haven't
@@ -362,10 +373,25 @@ static noinstr unsigned long xen_get_debugreg(int reg)
        return HYPERVISOR_get_debugreg(reg);
 }
 
+static void xen_start_context_switch(struct task_struct *prev)
+{
+       BUG_ON(preemptible());
+
+       if (this_cpu_read(xen_lazy_mode) == XEN_LAZY_MMU) {
+               arch_leave_lazy_mmu_mode();
+               set_ti_thread_flag(task_thread_info(prev), TIF_LAZY_MMU_UPDATES);
+       }
+       enter_lazy(XEN_LAZY_CPU);
+}
+
 static void xen_end_context_switch(struct task_struct *next)
 {
+       BUG_ON(preemptible());
+
        xen_mc_flush();
-       paravirt_end_context_switch(next);
+       leave_lazy(XEN_LAZY_CPU);
+       if (test_and_clear_ti_thread_flag(task_thread_info(next), TIF_LAZY_MMU_UPDATES))
+               arch_enter_lazy_mmu_mode();
 }
 
 static unsigned long xen_store_tr(void)
@@ -472,7 +498,7 @@ static void xen_set_ldt(const void *addr, unsigned entries)
 
        MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
 
-       xen_mc_issue(PARAVIRT_LAZY_CPU);
+       xen_mc_issue(XEN_LAZY_CPU);
 }
 
 static void xen_load_gdt(const struct desc_ptr *dtr)
@@ -568,7 +594,7 @@ static void xen_load_tls(struct thread_struct *t, unsigned int cpu)
         * exception between the new %fs descriptor being loaded and
         * %fs being effectively cleared at __switch_to().
         */
-       if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_CPU)
+       if (xen_get_lazy_mode() == XEN_LAZY_CPU)
                loadsegment(fs, 0);
 
        xen_mc_batch();
@@ -577,7 +603,7 @@ static void xen_load_tls(struct thread_struct *t, unsigned int cpu)
        load_TLS_descriptor(t, cpu, 1);
        load_TLS_descriptor(t, cpu, 2);
 
-       xen_mc_issue(PARAVIRT_LAZY_CPU);
+       xen_mc_issue(XEN_LAZY_CPU);
 }
 
 static void xen_load_gs_index(unsigned int idx)
@@ -909,7 +935,7 @@ static void xen_load_sp0(unsigned long sp0)
 
        mcs = xen_mc_entry(0);
        MULTI_stack_switch(mcs.mc, __KERNEL_DS, sp0);
-       xen_mc_issue(PARAVIRT_LAZY_CPU);
+       xen_mc_issue(XEN_LAZY_CPU);
        this_cpu_write(cpu_tss_rw.x86_tss.sp0, sp0);
 }
 
@@ -973,7 +999,7 @@ static void xen_write_cr0(unsigned long cr0)
 
        MULTI_fpu_taskswitch(mcs.mc, (cr0 & X86_CR0_TS) != 0);
 
-       xen_mc_issue(PARAVIRT_LAZY_CPU);
+       xen_mc_issue(XEN_LAZY_CPU);
 }
 
 static void xen_write_cr4(unsigned long cr4)
@@ -1156,7 +1182,7 @@ static const typeof(pv_ops) xen_cpu_ops __initconst = {
 #endif
                .io_delay = xen_io_delay,
 
-               .start_context_switch = paravirt_start_context_switch,
+               .start_context_switch = xen_start_context_switch,
                .end_context_switch = xen_end_context_switch,
        },
 };
index 1652c39e3dfbd309278f887233c026736a96b9a2..b6830554ff6905633fc543fb39e1b5b4a024bb07 100644 (file)
@@ -236,7 +236,7 @@ static void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val)
        u.val = pmd_val_ma(val);
        xen_extend_mmu_update(&u);
 
-       xen_mc_issue(PARAVIRT_LAZY_MMU);
+       xen_mc_issue(XEN_LAZY_MMU);
 
        preempt_enable();
 }
@@ -270,7 +270,7 @@ static bool xen_batched_set_pte(pte_t *ptep, pte_t pteval)
 {
        struct mmu_update u;
 
-       if (paravirt_get_lazy_mode() != PARAVIRT_LAZY_MMU)
+       if (xen_get_lazy_mode() != XEN_LAZY_MMU)
                return false;
 
        xen_mc_batch();
@@ -279,7 +279,7 @@ static bool xen_batched_set_pte(pte_t *ptep, pte_t pteval)
        u.val = pte_val_ma(pteval);
        xen_extend_mmu_update(&u);
 
-       xen_mc_issue(PARAVIRT_LAZY_MMU);
+       xen_mc_issue(XEN_LAZY_MMU);
 
        return true;
 }
@@ -325,7 +325,7 @@ void xen_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr,
        u.val = pte_val_ma(pte);
        xen_extend_mmu_update(&u);
 
-       xen_mc_issue(PARAVIRT_LAZY_MMU);
+       xen_mc_issue(XEN_LAZY_MMU);
 }
 
 /* Assume pteval_t is equivalent to all the other *val_t types. */
@@ -419,7 +419,7 @@ static void xen_set_pud_hyper(pud_t *ptr, pud_t val)
        u.val = pud_val_ma(val);
        xen_extend_mmu_update(&u);
 
-       xen_mc_issue(PARAVIRT_LAZY_MMU);
+       xen_mc_issue(XEN_LAZY_MMU);
 
        preempt_enable();
 }
@@ -499,7 +499,7 @@ static void __init xen_set_p4d_hyper(p4d_t *ptr, p4d_t val)
 
        __xen_set_p4d_hyper(ptr, val);
 
-       xen_mc_issue(PARAVIRT_LAZY_MMU);
+       xen_mc_issue(XEN_LAZY_MMU);
 
        preempt_enable();
 }
@@ -531,7 +531,7 @@ static void xen_set_p4d(p4d_t *ptr, p4d_t val)
        if (user_ptr)
                __xen_set_p4d_hyper((p4d_t *)user_ptr, val);
 
-       xen_mc_issue(PARAVIRT_LAZY_MMU);
+       xen_mc_issue(XEN_LAZY_MMU);
 }
 
 #if CONFIG_PGTABLE_LEVELS >= 5
@@ -1245,7 +1245,7 @@ static noinline void xen_flush_tlb(void)
        op->cmd = MMUEXT_TLB_FLUSH_LOCAL;
        MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
 
-       xen_mc_issue(PARAVIRT_LAZY_MMU);
+       xen_mc_issue(XEN_LAZY_MMU);
 
        preempt_enable();
 }
@@ -1265,7 +1265,7 @@ static void xen_flush_tlb_one_user(unsigned long addr)
        op->arg1.linear_addr = addr & PAGE_MASK;
        MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
 
-       xen_mc_issue(PARAVIRT_LAZY_MMU);
+       xen_mc_issue(XEN_LAZY_MMU);
 
        preempt_enable();
 }
@@ -1302,7 +1302,7 @@ static void xen_flush_tlb_multi(const struct cpumask *cpus,
 
        MULTI_mmuext_op(mcs.mc, &args->op, 1, NULL, DOMID_SELF);
 
-       xen_mc_issue(PARAVIRT_LAZY_MMU);
+       xen_mc_issue(XEN_LAZY_MMU);
 }
 
 static unsigned long xen_read_cr3(void)
@@ -1361,7 +1361,7 @@ static void xen_write_cr3(unsigned long cr3)
        else
                __xen_write_cr3(false, 0);
 
-       xen_mc_issue(PARAVIRT_LAZY_CPU);  /* interrupts restored */
+       xen_mc_issue(XEN_LAZY_CPU);  /* interrupts restored */
 }
 
 /*
@@ -1396,7 +1396,7 @@ static void __init xen_write_cr3_init(unsigned long cr3)
 
        __xen_write_cr3(true, cr3);
 
-       xen_mc_issue(PARAVIRT_LAZY_CPU);  /* interrupts restored */
+       xen_mc_issue(XEN_LAZY_CPU);  /* interrupts restored */
 }
 
 static int xen_pgd_alloc(struct mm_struct *mm)
@@ -1557,7 +1557,7 @@ static inline void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn,
                if (level == PT_PTE && USE_SPLIT_PTE_PTLOCKS && !pinned)
                        __pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn);
 
-               xen_mc_issue(PARAVIRT_LAZY_MMU);
+               xen_mc_issue(XEN_LAZY_MMU);
        }
 }
 
@@ -1587,7 +1587,7 @@ static inline void xen_release_ptpage(unsigned long pfn, unsigned level)
 
                __set_pfn_prot(pfn, PAGE_KERNEL);
 
-               xen_mc_issue(PARAVIRT_LAZY_MMU);
+               xen_mc_issue(XEN_LAZY_MMU);
 
                ClearPagePinned(page);
        }
@@ -1804,7 +1804,7 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
         */
        xen_mc_batch();
        __xen_write_cr3(true, __pa(init_top_pgt));
-       xen_mc_issue(PARAVIRT_LAZY_CPU);
+       xen_mc_issue(XEN_LAZY_CPU);
 
        /* We can't that easily rip out L3 and L2, as the Xen pagetables are
         * set out this way: [L4], [L1], [L2], [L3], [L1], [L1] ...  for
@@ -2083,6 +2083,23 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
 #endif
 }
 
+static void xen_enter_lazy_mmu(void)
+{
+       enter_lazy(XEN_LAZY_MMU);
+}
+
+static void xen_flush_lazy_mmu(void)
+{
+       preempt_disable();
+
+       if (xen_get_lazy_mode() == XEN_LAZY_MMU) {
+               arch_leave_lazy_mmu_mode();
+               arch_enter_lazy_mmu_mode();
+       }
+
+       preempt_enable();
+}
+
 static void __init xen_post_allocator_init(void)
 {
        pv_ops.mmu.set_pte = xen_set_pte;
@@ -2107,7 +2124,7 @@ static void xen_leave_lazy_mmu(void)
 {
        preempt_disable();
        xen_mc_flush();
-       paravirt_leave_lazy_mmu();
+       leave_lazy(XEN_LAZY_MMU);
        preempt_enable();
 }
 
@@ -2166,9 +2183,9 @@ static const typeof(pv_ops) xen_mmu_ops __initconst = {
                .exit_mmap = xen_exit_mmap,
 
                .lazy_mode = {
-                       .enter = paravirt_enter_lazy_mmu,
+                       .enter = xen_enter_lazy_mmu,
                        .leave = xen_leave_lazy_mmu,
-                       .flush = paravirt_flush_lazy_mmu,
+                       .flush = xen_flush_lazy_mmu,
                },
 
                .set_fixmap = xen_set_fixmap,
@@ -2385,7 +2402,7 @@ static noinline void xen_flush_tlb_all(void)
        op->cmd = MMUEXT_TLB_FLUSH_ALL;
        MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
 
-       xen_mc_issue(PARAVIRT_LAZY_MMU);
+       xen_mc_issue(XEN_LAZY_MMU);
 
        preempt_enable();
 }
index 1c51b2c87f30a12dfb8d022c54de1f88046234ef..c3867b585e0d8d56419c5a6641f5c2eeb3a30a16 100644 (file)
@@ -26,7 +26,7 @@ static inline void xen_mc_batch(void)
 
        /* need to disable interrupts until this entry is complete */
        local_irq_save(flags);
-       trace_xen_mc_batch(paravirt_get_lazy_mode());
+       trace_xen_mc_batch(xen_get_lazy_mode());
        __this_cpu_write(xen_mc_irq_flags, flags);
 }
 
@@ -44,7 +44,7 @@ static inline void xen_mc_issue(unsigned mode)
 {
        trace_xen_mc_issue(mode);
 
-       if ((paravirt_get_lazy_mode() & mode) == 0)
+       if ((xen_get_lazy_mode() & mode) == 0)
                xen_mc_flush();
 
        /* restore flags saved in xen_mc_batch */
index ec922c6bccbe20737d21e03a4d4964c8dab1d66f..1fafd54dce3cb9e9f51fb3a4cb0cb6e907a1c066 100644 (file)
@@ -4405,11 +4405,8 @@ static int blk_mq_realloc_tag_set_tags(struct blk_mq_tag_set *set,
        struct blk_mq_tags **new_tags;
        int i;
 
-       if (set->nr_hw_queues >= new_nr_hw_queues) {
-               for (i = new_nr_hw_queues; i < set->nr_hw_queues; i++)
-                       __blk_mq_free_map_and_rqs(set, i);
+       if (set->nr_hw_queues >= new_nr_hw_queues)
                goto done;
-       }
 
        new_tags = kcalloc_node(new_nr_hw_queues, sizeof(struct blk_mq_tags *),
                                GFP_KERNEL, set->numa_node);
@@ -4719,7 +4716,8 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
 {
        struct request_queue *q;
        LIST_HEAD(head);
-       int prev_nr_hw_queues;
+       int prev_nr_hw_queues = set->nr_hw_queues;
+       int i;
 
        lockdep_assert_held(&set->tag_list_lock);
 
@@ -4746,7 +4744,6 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
                blk_mq_sysfs_unregister_hctxs(q);
        }
 
-       prev_nr_hw_queues = set->nr_hw_queues;
        if (blk_mq_realloc_tag_set_tags(set, nr_hw_queues) < 0)
                goto reregister;
 
@@ -4781,6 +4778,10 @@ switch_back:
 
        list_for_each_entry(q, &set->tag_list, tag_set_list)
                blk_mq_unfreeze_queue(q);
+
+       /* Free the excess tags when nr_hw_queues shrink. */
+       for (i = set->nr_hw_queues; i < prev_nr_hw_queues; i++)
+               __blk_mq_free_map_and_rqs(set, i);
 }
 
 void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues)
index 285b3cb7c0bc781b4c8be08b1c2c32a931ad0c3c..5ab120d74c592b77dd53c9a44a9c68ab9138f5dd 100644 (file)
@@ -278,10 +278,14 @@ int sm2_compute_z_digest(struct shash_desc *desc,
        if (!ec)
                return -ENOMEM;
 
-       err = __sm2_set_pub_key(ec, key, keylen);
+       err = sm2_ec_ctx_init(ec);
        if (err)
                goto out_free_ec;
 
+       err = __sm2_set_pub_key(ec, key, keylen);
+       if (err)
+               goto out_deinit_ec;
+
        bits_len = SM2_DEFAULT_USERID_LEN * 8;
        entl[0] = bits_len >> 8;
        entl[1] = bits_len & 0xff;
index cb0afca2e4a04b6aa8e58210dd550528e431cce9..1bec7819a837ab86c0169ca4b6a06b2d37b5483c 100644 (file)
@@ -46,7 +46,7 @@ obj-$(CONFIG_DMADEVICES)      += dma/
 
 # SOC specific infrastructure drivers.
 obj-y                          += soc/
-obj-$(CONFIG_PM_GENERIC_DOMAINS)       += genpd/
+obj-$(CONFIG_PM_GENERIC_DOMAINS)       += pmdomain/
 
 obj-y                          += virtio/
 obj-$(CONFIG_VDPA)             += vdpa/
index 34626d66fa10284263435dda3c62866ce6853d55..00c5dbbe68478c9f6422da8d1b0ea0de8fb2aa76 100644 (file)
@@ -1046,7 +1046,8 @@ static irqreturn_t ivpu_hw_40xx_irqb_handler(struct ivpu_device *vdev, int irq)
        if (status == 0)
                return IRQ_NONE;
 
-       REGB_WR32(VPU_40XX_BUTTRESS_INTERRUPT_STAT, status);
+       /* Disable global interrupt before handling local buttress interrupts */
+       REGB_WR32(VPU_40XX_BUTTRESS_GLOBAL_INT_MASK, 0x1);
 
        if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE, status))
                ivpu_dbg(vdev, IRQ, "FREQ_CHANGE");
@@ -1092,6 +1093,12 @@ static irqreturn_t ivpu_hw_40xx_irqb_handler(struct ivpu_device *vdev, int irq)
                schedule_recovery = true;
        }
 
+       /* This must be done after interrupts are cleared at the source. */
+       REGB_WR32(VPU_40XX_BUTTRESS_INTERRUPT_STAT, status);
+
+       /* Re-enable global interrupt */
+       REGB_WR32(VPU_40XX_BUTTRESS_GLOBAL_INT_MASK, 0x0);
+
        if (schedule_recovery)
                ivpu_pm_schedule_recovery(vdev);
 
index 1a8591e9a9bf1a215b058ee227e6b1ec8fe8c4d5..994091bd52de4027877638c66a02d41e100b4748 100644 (file)
@@ -19,6 +19,7 @@ static void acpi_set_pdc_bits(u32 *buf)
 {
        buf[0] = ACPI_PDC_REVISION_ID;
        buf[1] = 1;
+       buf[2] = 0;
 
        /* Twiddle arch-specific bits needed for _PDC */
        arch_acpi_set_proc_cap_bits(&buf[2]);
index f14e68266ccd473db98bef2bcfe118bfae47afc5..312730f8272eeca4edc6d6695469b25497e57e15 100644 (file)
@@ -492,7 +492,7 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
 }
 
 static int thermal_get_trend(struct thermal_zone_device *thermal,
-                            struct thermal_trip *trip,
+                            const struct thermal_trip *trip,
                             enum thermal_trend *trend)
 {
        struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
index abb5911c9d09159264436ef0dcc344d1edc72c7e..08745e7db8201fcfd95bb63767b529e2ce337a60 100644 (file)
@@ -1883,6 +1883,15 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        else
                dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n");
 
+       if (!(hpriv->cap & HOST_CAP_PART))
+               host->flags |= ATA_HOST_NO_PART;
+
+       if (!(hpriv->cap & HOST_CAP_SSC))
+               host->flags |= ATA_HOST_NO_SSC;
+
+       if (!(hpriv->cap2 & HOST_CAP2_SDS))
+               host->flags |= ATA_HOST_NO_DEVSLP;
+
        if (pi.flags & ATA_FLAG_EM)
                ahci_reset_em(host);
 
index e2bacedf28ef5be940959628969c64e569f6320d..f1263364fa97fa5f37f878f5a16c376290fb9e18 100644 (file)
@@ -1256,6 +1256,26 @@ static ssize_t ahci_activity_show(struct ata_device *dev, char *buf)
        return sprintf(buf, "%d\n", emp->blink_policy);
 }
 
+static void ahci_port_clear_pending_irq(struct ata_port *ap)
+{
+       struct ahci_host_priv *hpriv = ap->host->private_data;
+       void __iomem *port_mmio = ahci_port_base(ap);
+       u32 tmp;
+
+       /* clear SError */
+       tmp = readl(port_mmio + PORT_SCR_ERR);
+       dev_dbg(ap->host->dev, "PORT_SCR_ERR 0x%x\n", tmp);
+       writel(tmp, port_mmio + PORT_SCR_ERR);
+
+       /* clear port IRQ */
+       tmp = readl(port_mmio + PORT_IRQ_STAT);
+       dev_dbg(ap->host->dev, "PORT_IRQ_STAT 0x%x\n", tmp);
+       if (tmp)
+               writel(tmp, port_mmio + PORT_IRQ_STAT);
+
+       writel(1 << ap->port_no, hpriv->mmio + HOST_IRQ_STAT);
+}
+
 static void ahci_port_init(struct device *dev, struct ata_port *ap,
                           int port_no, void __iomem *mmio,
                           void __iomem *port_mmio)
@@ -1270,18 +1290,7 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap,
        if (rc)
                dev_warn(dev, "%s (%d)\n", emsg, rc);
 
-       /* clear SError */
-       tmp = readl(port_mmio + PORT_SCR_ERR);
-       dev_dbg(dev, "PORT_SCR_ERR 0x%x\n", tmp);
-       writel(tmp, port_mmio + PORT_SCR_ERR);
-
-       /* clear port IRQ */
-       tmp = readl(port_mmio + PORT_IRQ_STAT);
-       dev_dbg(dev, "PORT_IRQ_STAT 0x%x\n", tmp);
-       if (tmp)
-               writel(tmp, port_mmio + PORT_IRQ_STAT);
-
-       writel(1 << port_no, mmio + HOST_IRQ_STAT);
+       ahci_port_clear_pending_irq(ap);
 
        /* mark esata ports */
        tmp = readl(port_mmio + PORT_CMD);
@@ -1603,6 +1612,8 @@ int ahci_do_hardreset(struct ata_link *link, unsigned int *class,
        tf.status = ATA_BUSY;
        ata_tf_to_fis(&tf, 0, 0, d2h_fis);
 
+       ahci_port_clear_pending_irq(ap);
+
        rc = sata_link_hardreset(link, timing, deadline, online,
                                 ahci_check_ready);
 
index 74314311295fe43d56241fae063bee6cd530267a..0072e0f9ad391195368ae2e9c77e5e7fa4cc0195 100644 (file)
@@ -4783,11 +4783,8 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
         * been aborted by the device due to a limit timeout using the policy
         * 0xD. For these commands, invoke EH to get the command sense data.
         */
-       if (qc->result_tf.status & ATA_SENSE &&
-           ((ata_is_ncq(qc->tf.protocol) &&
-             dev->flags & ATA_DFLAG_CDL_ENABLED) ||
-            (!ata_is_ncq(qc->tf.protocol) &&
-             ata_id_sense_reporting_enabled(dev->id)))) {
+       if (qc->flags & ATA_QCFLAG_HAS_CDL &&
+           qc->result_tf.status & ATA_SENSE) {
                /*
                 * Tell SCSI EH to not overwrite scmd->result even if this
                 * command is finished with result SAM_STAT_GOOD.
index 159ba6ba19ebb7872b87c2bfe03bae8e17023321..4cf4f57e57b8bdf06b5353e01ea4236c45f705e4 100644 (file)
@@ -2796,23 +2796,13 @@ int ata_eh_reset(struct ata_link *link, int classify,
                }
        }
 
-       /*
-        * Some controllers can't be frozen very well and may set spurious
-        * error conditions during reset.  Clear accumulated error
-        * information and re-thaw the port if frozen.  As reset is the
-        * final recovery action and we cross check link onlineness against
-        * device classification later, no hotplug event is lost by this.
-        */
+       /* clear cached SError */
        spin_lock_irqsave(link->ap->lock, flags);
-       memset(&link->eh_info, 0, sizeof(link->eh_info));
+       link->eh_info.serror = 0;
        if (slave)
-               memset(&slave->eh_info, 0, sizeof(link->eh_info));
-       ap->pflags &= ~ATA_PFLAG_EH_PENDING;
+               slave->eh_info.serror = 0;
        spin_unlock_irqrestore(link->ap->lock, flags);
 
-       if (ata_port_is_frozen(ap))
-               ata_eh_thaw_port(ap);
-
        /*
         * Make sure onlineness and classification result correspond.
         * Hotplug could have happened during reset and some
index 5d31c08be0136cc0ff6baeac1d9f6041be48b5fb..a701e1538482f09eb5960a606edad01f34920401 100644 (file)
@@ -396,10 +396,23 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
        case ATA_LPM_MED_POWER_WITH_DIPM:
        case ATA_LPM_MIN_POWER_WITH_PARTIAL:
        case ATA_LPM_MIN_POWER:
-               if (ata_link_nr_enabled(link) > 0)
-                       /* no restrictions on LPM transitions */
+               if (ata_link_nr_enabled(link) > 0) {
+                       /* assume no restrictions on LPM transitions */
                        scontrol &= ~(0x7 << 8);
-               else {
+
+                       /*
+                        * If the controller does not support partial, slumber,
+                        * or devsleep, then disallow these transitions.
+                        */
+                       if (link->ap->host->flags & ATA_HOST_NO_PART)
+                               scontrol |= (0x1 << 8);
+
+                       if (link->ap->host->flags & ATA_HOST_NO_SSC)
+                               scontrol |= (0x2 << 8);
+
+                       if (link->ap->host->flags & ATA_HOST_NO_DEVSLP)
+                               scontrol |= (0x4 << 8);
+               } else {
                        /* empty port, power off */
                        scontrol &= ~0xf;
                        scontrol |= (0x1 << 2);
index 4839becbbd5646f11c187611d0554a726bad515c..94b8d352102e85c0e70a1cedf8c55a15abb2b9cd 100644 (file)
@@ -37,7 +37,7 @@ static int comm_read_regr(struct pi_adapter *pi, int cont, int regr)
 {
        int l, h, r;
 
-        r = regr + cont_map[cont];
+       r = regr + cont_map[cont];
 
        switch (pi->mode) {
        case 0:
@@ -90,7 +90,6 @@ static void comm_connect(struct pi_adapter *pi)
 }
 
 static void comm_disconnect(struct pi_adapter *pi)
-
 {
        w2(0); w2(0); w2(0); w2(4);
        w0(pi->saved_r0);
@@ -172,12 +171,12 @@ static void comm_write_block(struct pi_adapter *pi, char *buf, int count)
                        w4l(swab16(((u16 *)buf)[2 * k]) |
                            swab16(((u16 *)buf)[2 * k + 1]) << 16);
                break;
-        }
+       }
 }
 
 static void comm_log_adapter(struct pi_adapter *pi)
-
-{       char *mode_string[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" };
+{
+       char *mode_string[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" };
 
        dev_info(&pi->dev,
                 "DataStor Commuter at 0x%x, mode %d (%s), delay %d\n",
index d105db5c7d81a6b15fd68bee9f9ad9c17799a55c..45e48d653c60b5556557e4e4d12666a32b7563aa 100644 (file)
@@ -1255,8 +1255,8 @@ static void mv_dump_mem(struct device *dev, void __iomem *start, unsigned bytes)
 
        for (b = 0; b < bytes; ) {
                for (w = 0, o = 0; b < bytes && w < 4; w++) {
-                       o += snprintf(linebuf + o, sizeof(linebuf) - o,
-                                     "%08x ", readl(start + b));
+                       o += scnprintf(linebuf + o, sizeof(linebuf) - o,
+                                      "%08x ", readl(start + b));
                        b += sizeof(u32);
                }
                dev_dbg(dev, "%s: %p: %s\n",
index b7d7f410c2561ca26da0efd5808e2273028c0759..4d8b315c48a15a9dd9db023f67e214855b86623d 100644 (file)
@@ -3537,6 +3537,8 @@ int device_add(struct device *dev)
        /* subsystems can specify simple device enumeration */
        else if (dev->bus && dev->bus->dev_name)
                error = dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);
+       else
+               error = -EINVAL;
        if (error)
                goto name_error;
 
index 514f9f287a781dd910de9da4034a6ea74529bc11..c6f181702b9a7bddebf90dbd56d6c7dd259a4df2 100644 (file)
@@ -394,8 +394,6 @@ find_quicksilver(struct device *dev, void *data)
 static int __init
 parisc_agp_init(void)
 {
-       extern struct sba_device *sba_list;
-
        int err = -1;
        struct parisc_device *sba = NULL, *lba = NULL;
        struct lba_device *lbadev = NULL;
index 23f6f2eda84c080308d3e2fa0422edec34b33839..42b1062e33cd5d81ec7cc3ca9f2baf694d8365da 100644 (file)
@@ -33,7 +33,7 @@ const struct class tpm_class = {
        .shutdown_pre = tpm_class_shutdown,
 };
 const struct class tpmrm_class = {
-       .name = "tmprm",
+       .name = "tpmrm",
 };
 dev_t tpm_devt;
 
index 7a8d402f05be1668b1d084ad08f4834c8560cd5b..9af280735cbaa1db0d59dc154bcb3be7c1cc7df1 100644 (file)
@@ -67,7 +67,6 @@ config COMEDI_TEST
 
 config COMEDI_PARPORT
        tristate "Parallel port support"
-       depends on HAS_IOPORT
        help
          Enable support for the standard parallel port.
          A cheap and easy way to get a few more digital I/O lines. Steal
@@ -80,7 +79,6 @@ config COMEDI_PARPORT
 config COMEDI_SSV_DNP
        tristate "SSV Embedded Systems DIL/Net-PC support"
        depends on X86_32 || COMPILE_TEST
-       depends on HAS_IOPORT
        help
          Enable support for SSV Embedded Systems DIL/Net-PC
 
@@ -91,7 +89,6 @@ endif # COMEDI_MISC_DRIVERS
 
 menuconfig COMEDI_ISA_DRIVERS
        bool "Comedi ISA and PC/104 drivers"
-       depends on ISA
        help
          Enable comedi ISA and PC/104 drivers to be built
 
@@ -103,8 +100,7 @@ if COMEDI_ISA_DRIVERS
 
 config COMEDI_PCL711
        tristate "Advantech PCL-711/711b and ADlink ACL-8112 ISA card support"
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        help
          Enable support for Advantech PCL-711 and 711b, ADlink ACL-8112
 
@@ -165,9 +161,8 @@ config COMEDI_PCL730
 
 config COMEDI_PCL812
        tristate "Advantech PCL-812/813 and ADlink ACL-8112/8113/8113/8216"
-       depends on HAS_IOPORT
        select COMEDI_ISADMA if ISA_DMA_API
-       depends on COMEDI_8254
+       select COMEDI_8254
        help
          Enable support for Advantech PCL-812/PG, PCL-813/B, ADLink
          ACL-8112DG/HG/PG, ACL-8113, ACL-8216, ICP DAS A-821PGH/PGL/PGL-NDA,
@@ -178,9 +173,8 @@ config COMEDI_PCL812
 
 config COMEDI_PCL816
        tristate "Advantech PCL-814 and PCL-816 ISA card support"
-       depends on HAS_IOPORT
        select COMEDI_ISADMA if ISA_DMA_API
-       depends on COMEDI_8254
+       select COMEDI_8254
        help
          Enable support for Advantech PCL-814 and PCL-816 ISA cards
 
@@ -189,9 +183,8 @@ config COMEDI_PCL816
 
 config COMEDI_PCL818
        tristate "Advantech PCL-718 and PCL-818 ISA card support"
-       depends on HAS_IOPORT
        select COMEDI_ISADMA if ISA_DMA_API
-       depends on COMEDI_8254
+       select COMEDI_8254
        help
          Enable support for Advantech PCL-818 ISA cards
          PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818 and PCL-718
@@ -210,7 +203,7 @@ config COMEDI_PCM3724
 
 config COMEDI_AMPLC_DIO200_ISA
        tristate "Amplicon PC212E/PC214E/PC215E/PC218E/PC272E"
-       depends on COMEDI_AMPLC_DIO200
+       select COMEDI_AMPLC_DIO200
        help
          Enable support for Amplicon PC212E, PC214E, PC215E, PC218E and
          PC272E ISA DIO boards
@@ -262,8 +255,7 @@ config COMEDI_DAC02
 
 config COMEDI_DAS16M1
        tristate "MeasurementComputing CIO-DAS16/M1DAS-16 ISA card support"
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        select COMEDI_8255
        help
          Enable support for Measurement Computing CIO-DAS16/M1 ISA cards.
@@ -273,7 +265,7 @@ config COMEDI_DAS16M1
 
 config COMEDI_DAS08_ISA
        tristate "DAS-08 compatible ISA and PC/104 card support"
-       depends on COMEDI_DAS08
+       select COMEDI_DAS08
        help
          Enable support for Keithley Metrabyte/ComputerBoards DAS08
          and compatible ISA and PC/104 cards:
@@ -286,9 +278,8 @@ config COMEDI_DAS08_ISA
 
 config COMEDI_DAS16
        tristate "DAS-16 compatible ISA and PC/104 card support"
-       depends on HAS_IOPORT
        select COMEDI_ISADMA if ISA_DMA_API
-       depends on COMEDI_8254
+       select COMEDI_8254
        select COMEDI_8255
        help
          Enable support for Keithley Metrabyte/ComputerBoards DAS16
@@ -305,8 +296,7 @@ config COMEDI_DAS16
 
 config COMEDI_DAS800
        tristate "DAS800 and compatible ISA card support"
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        help
          Enable support for Keithley Metrabyte DAS800 and compatible ISA cards
          Keithley Metrabyte DAS-800, DAS-801, DAS-802
@@ -318,9 +308,8 @@ config COMEDI_DAS800
 
 config COMEDI_DAS1800
        tristate "DAS1800 and compatible ISA card support"
-       depends on HAS_IOPORT
        select COMEDI_ISADMA if ISA_DMA_API
-       depends on COMEDI_8254
+       select COMEDI_8254
        help
          Enable support for DAS1800 and compatible ISA cards
          Keithley Metrabyte DAS-1701ST, DAS-1701ST-DA, DAS-1701/AO,
@@ -334,8 +323,7 @@ config COMEDI_DAS1800
 
 config COMEDI_DAS6402
        tristate "DAS6402 and compatible ISA card support"
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        help
          Enable support for DAS6402 and compatible ISA cards
          Computerboards, Keithley Metrabyte DAS6402 and compatibles
@@ -414,8 +402,7 @@ config COMEDI_FL512
 
 config COMEDI_AIO_AIO12_8
        tristate "I/O Products PC/104 AIO12-8 Analog I/O Board support"
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        select COMEDI_8255
        help
          Enable support for I/O Products PC/104 AIO12-8 Analog I/O Board
@@ -469,9 +456,8 @@ config COMEDI_ADQ12B
 
 config COMEDI_NI_AT_A2150
        tristate "NI AT-A2150 ISA card support"
-       depends on HAS_IOPORT
        select COMEDI_ISADMA if ISA_DMA_API
-       depends on COMEDI_8254
+       select COMEDI_8254
        help
          Enable support for National Instruments AT-A2150 cards
 
@@ -480,8 +466,7 @@ config COMEDI_NI_AT_A2150
 
 config COMEDI_NI_AT_AO
        tristate "NI AT-AO-6/10 EISA card support"
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        help
          Enable support for National Instruments AT-AO-6/10 cards
 
@@ -512,7 +497,7 @@ config COMEDI_NI_ATMIO16D
 
 config COMEDI_NI_LABPC_ISA
        tristate "NI Lab-PC and compatibles ISA support"
-       depends on COMEDI_NI_LABPC
+       select COMEDI_NI_LABPC
        help
          Enable support for National Instruments Lab-PC and compatibles
          Lab-PC-1200, Lab-PC-1200AI, Lab-PC+.
@@ -576,7 +561,7 @@ endif # COMEDI_ISA_DRIVERS
 
 menuconfig COMEDI_PCI_DRIVERS
        tristate "Comedi PCI drivers"
-       depends on PCI && HAS_IOPORT
+       depends on PCI
        help
          Enable support for comedi PCI drivers.
 
@@ -725,8 +710,7 @@ config COMEDI_ADL_PCI8164
 
 config COMEDI_ADL_PCI9111
        tristate "ADLink PCI-9111HR support"
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        help
          Enable support for ADlink PCI9111 cards
 
@@ -736,7 +720,7 @@ config COMEDI_ADL_PCI9111
 config COMEDI_ADL_PCI9118
        tristate "ADLink PCI-9118DG, PCI-9118HG, PCI-9118HR support"
        depends on HAS_DMA
-       depends on COMEDI_8254
+       select COMEDI_8254
        help
          Enable support for ADlink PCI-9118DG, PCI-9118HG, PCI-9118HR cards
 
@@ -745,8 +729,7 @@ config COMEDI_ADL_PCI9118
 
 config COMEDI_ADV_PCI1710
        tristate "Advantech PCI-171x and PCI-1731 support"
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        help
          Enable support for Advantech PCI-1710, PCI-1710HG, PCI-1711,
          PCI-1713 and PCI-1731
@@ -790,8 +773,7 @@ config COMEDI_ADV_PCI1760
 
 config COMEDI_ADV_PCI_DIO
        tristate "Advantech PCI DIO card support"
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        select COMEDI_8255
        help
          Enable support for Advantech PCI DIO cards
@@ -804,7 +786,7 @@ config COMEDI_ADV_PCI_DIO
 
 config COMEDI_AMPLC_DIO200_PCI
        tristate "Amplicon PCI215/PCI272/PCIe215/PCIe236/PCIe296 DIO support"
-       depends on COMEDI_AMPLC_DIO200
+       select COMEDI_AMPLC_DIO200
        help
          Enable support for Amplicon PCI215, PCI272, PCIe215, PCIe236
          and PCIe296 DIO boards.
@@ -832,8 +814,7 @@ config COMEDI_AMPLC_PC263_PCI
 
 config COMEDI_AMPLC_PCI224
        tristate "Amplicon PCI224 and PCI234 support"
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        help
          Enable support for Amplicon PCI224 and PCI234 AO boards
 
@@ -842,8 +823,7 @@ config COMEDI_AMPLC_PCI224
 
 config COMEDI_AMPLC_PCI230
        tristate "Amplicon PCI230 and PCI260 support"
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        select COMEDI_8255
        help
          Enable support for Amplicon PCI230 and PCI260 Multifunction I/O
@@ -862,7 +842,7 @@ config COMEDI_CONTEC_PCI_DIO
 
 config COMEDI_DAS08_PCI
        tristate "DAS-08 PCI support"
-       depends on COMEDI_DAS08
+       select COMEDI_DAS08
        help
          Enable support for PCI DAS-08 cards.
 
@@ -949,8 +929,7 @@ config COMEDI_CB_PCIDAS64
 
 config COMEDI_CB_PCIDAS
        tristate "MeasurementComputing PCI-DAS support"
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        select COMEDI_8255
        help
          Enable support for ComputerBoards/MeasurementComputing PCI-DAS with
@@ -974,8 +953,7 @@ config COMEDI_CB_PCIDDA
 
 config COMEDI_CB_PCIMDAS
        tristate "MeasurementComputing PCIM-DAS1602/16, PCIe-DAS1602/16 support"
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        select COMEDI_8255
        help
          Enable support for ComputerBoards/MeasurementComputing PCI Migration
@@ -995,8 +973,7 @@ config COMEDI_CB_PCIMDDA
 
 config COMEDI_ME4000
        tristate "Meilhaus ME-4000 support"
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        help
          Enable support for Meilhaus PCI data acquisition cards
          ME-4650, ME-4670i, ME-4680, ME-4680i and ME-4680is
@@ -1054,7 +1031,7 @@ config COMEDI_NI_670X
 
 config COMEDI_NI_LABPC_PCI
        tristate "NI Lab-PC PCI-1200 support"
-       depends on COMEDI_NI_LABPC
+       select COMEDI_NI_LABPC
        help
          Enable support for National Instruments Lab-PC PCI-1200.
 
@@ -1076,7 +1053,6 @@ config COMEDI_NI_PCIDIO
 config COMEDI_NI_PCIMIO
        tristate "NI PCI-MIO-E series and M series support"
        depends on HAS_DMA
-       depends on HAS_IOPORT
        select COMEDI_NI_TIOCMD
        select COMEDI_8255
        help
@@ -1098,8 +1074,7 @@ config COMEDI_NI_PCIMIO
 
 config COMEDI_RTD520
        tristate "Real Time Devices PCI4520/DM7520 support"
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        help
          Enable support for Real Time Devices PCI4520/DM7520
 
@@ -1139,8 +1114,7 @@ if COMEDI_PCMCIA_DRIVERS
 
 config COMEDI_CB_DAS16_CS
        tristate "CB DAS16 series PCMCIA support"
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        help
          Enable support for the ComputerBoards/MeasurementComputing PCMCIA
          cards DAS16/16, PCM-DAS16D/12 and PCM-DAS16s/16
@@ -1150,7 +1124,7 @@ config COMEDI_CB_DAS16_CS
 
 config COMEDI_DAS08_CS
        tristate "CB DAS08 PCMCIA support"
-       depends on COMEDI_DAS08
+       select COMEDI_DAS08
        help
          Enable support for the ComputerBoards/MeasurementComputing DAS-08
          PCMCIA card
@@ -1160,7 +1134,6 @@ config COMEDI_DAS08_CS
 
 config COMEDI_NI_DAQ_700_CS
        tristate "NI DAQCard-700 PCMCIA support"
-       depends on HAS_IOPORT
        help
          Enable support for the National Instruments PCMCIA DAQCard-700 DIO
 
@@ -1169,7 +1142,6 @@ config COMEDI_NI_DAQ_700_CS
 
 config COMEDI_NI_DAQ_DIO24_CS
        tristate "NI DAQ-Card DIO-24 PCMCIA support"
-       depends on HAS_IOPORT
        select COMEDI_8255
        help
          Enable support for the National Instruments PCMCIA DAQ-Card DIO-24
@@ -1179,7 +1151,7 @@ config COMEDI_NI_DAQ_DIO24_CS
 
 config COMEDI_NI_LABPC_CS
        tristate "NI DAQCard-1200 PCMCIA support"
-       depends on COMEDI_NI_LABPC
+       select COMEDI_NI_LABPC
        help
          Enable support for the National Instruments PCMCIA DAQCard-1200
 
@@ -1188,7 +1160,6 @@ config COMEDI_NI_LABPC_CS
 
 config COMEDI_NI_MIO_CS
        tristate "NI DAQCard E series PCMCIA support"
-       depends on HAS_IOPORT
        select COMEDI_NI_TIO
        select COMEDI_8255
        help
@@ -1201,7 +1172,6 @@ config COMEDI_NI_MIO_CS
 
 config COMEDI_QUATECH_DAQP_CS
        tristate "Quatech DAQP PCMCIA data capture card support"
-       depends on HAS_IOPORT
        help
          Enable support for the Quatech DAQP PCMCIA data capture cards
          DAQP-208 and DAQP-308
@@ -1278,14 +1248,12 @@ endif # COMEDI_USB_DRIVERS
 
 config COMEDI_8254
        tristate
-       depends on HAS_IOPORT
 
 config COMEDI_8255
        tristate
 
 config COMEDI_8255_SA
        tristate "Standalone 8255 support"
-       depends on HAS_IOPORT
        select COMEDI_8255
        help
          Enable support for 8255 digital I/O as a standalone driver.
@@ -1317,7 +1285,7 @@ config COMEDI_KCOMEDILIB
          called kcomedilib.
 
 config COMEDI_AMPLC_DIO200
-       depends on COMEDI_8254
+       select COMEDI_8254
        tristate
 
 config COMEDI_AMPLC_PC236
@@ -1326,7 +1294,7 @@ config COMEDI_AMPLC_PC236
 
 config COMEDI_DAS08
        tristate
-       depends on COMEDI_8254
+       select COMEDI_8254
        select COMEDI_8255
 
 config COMEDI_ISADMA
@@ -1334,8 +1302,7 @@ config COMEDI_ISADMA
 
 config COMEDI_NI_LABPC
        tristate
-       depends on HAS_IOPORT
-       depends on COMEDI_8254
+       select COMEDI_8254
        select COMEDI_8255
 
 config COMEDI_NI_LABPC_ISADMA
index d1c559879dcc00733cfb9abff6cffb64b0745659..40d055560e52fd2298fa3400384b686e37413b32 100644 (file)
@@ -14,7 +14,7 @@
 
 struct cxl_cxims_data {
        int nr_maps;
-       u64 xormaps[];
+       u64 xormaps[] __counted_by(nr_maps);
 };
 
 /*
@@ -112,9 +112,9 @@ static int cxl_parse_cxims(union acpi_subtable_headers *header, void *arg,
                              GFP_KERNEL);
        if (!cximsd)
                return -ENOMEM;
+       cximsd->nr_maps = nr_maps;
        memcpy(cximsd->xormaps, cxims->xormap_list,
               nr_maps * sizeof(*cximsd->xormaps));
-       cximsd->nr_maps = nr_maps;
        cxlrd->platform_data = cximsd;
 
        return 0;
index ca60bb8114f22a4df6f175b0f5a942e51e3cb45d..4df4f614f490ef96d26f412a9cff42e52d246486 100644 (file)
@@ -715,24 +715,25 @@ static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel)
        for (i = 0; i < cel_entries; i++) {
                u16 opcode = le16_to_cpu(cel_entry[i].opcode);
                struct cxl_mem_command *cmd = cxl_mem_find_command(opcode);
+               int enabled = 0;
 
-               if (!cmd && (!cxl_is_poison_command(opcode) ||
-                            !cxl_is_security_command(opcode))) {
-                       dev_dbg(dev,
-                               "Opcode 0x%04x unsupported by driver\n", opcode);
-                       continue;
-               }
-
-               if (cmd)
+               if (cmd) {
                        set_bit(cmd->info.id, mds->enabled_cmds);
+                       enabled++;
+               }
 
-               if (cxl_is_poison_command(opcode))
+               if (cxl_is_poison_command(opcode)) {
                        cxl_set_poison_cmd_enabled(&mds->poison, opcode);
+                       enabled++;
+               }
 
-               if (cxl_is_security_command(opcode))
+               if (cxl_is_security_command(opcode)) {
                        cxl_set_security_cmd_enabled(&mds->security, opcode);
+                       enabled++;
+               }
 
-               dev_dbg(dev, "Opcode 0x%04x enabled\n", opcode);
+               dev_dbg(dev, "Opcode 0x%04x %s\n", opcode,
+                       enabled ? "enabled" : "unsupported by driver");
        }
 }
 
index 724be8448eb4a52542bc3e0cd6b16de508f7979f..7ca01a834e188c8f09f2676b8c79689279acbabe 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright(c) 2020 Intel Corporation. All rights reserved. */
+#include <linux/platform_device.h>
 #include <linux/memregion.h>
 #include <linux/workqueue.h>
 #include <linux/debugfs.h>
@@ -706,16 +707,20 @@ static int cxl_setup_comp_regs(struct device *dev, struct cxl_register_map *map,
        return cxl_setup_regs(map);
 }
 
-static inline int cxl_port_setup_regs(struct cxl_port *port,
-                                     resource_size_t component_reg_phys)
+static int cxl_port_setup_regs(struct cxl_port *port,
+                       resource_size_t component_reg_phys)
 {
+       if (dev_is_platform(port->uport_dev))
+               return 0;
        return cxl_setup_comp_regs(&port->dev, &port->comp_map,
                                   component_reg_phys);
 }
 
-static inline int cxl_dport_setup_regs(struct cxl_dport *dport,
-                                      resource_size_t component_reg_phys)
+static int cxl_dport_setup_regs(struct cxl_dport *dport,
+                               resource_size_t component_reg_phys)
 {
+       if (dev_is_platform(dport->dport_dev))
+               return 0;
        return cxl_setup_comp_regs(dport->dport_dev, &dport->comp_map,
                                   component_reg_phys);
 }
index e115ba382e0445dc6c8ec1881e0e95ec307c4918..6d63b8798c29921470e37c9bf0e9d116c834508e 100644 (file)
@@ -717,13 +717,35 @@ static int match_free_decoder(struct device *dev, void *data)
        return 0;
 }
 
+static int match_auto_decoder(struct device *dev, void *data)
+{
+       struct cxl_region_params *p = data;
+       struct cxl_decoder *cxld;
+       struct range *r;
+
+       if (!is_switch_decoder(dev))
+               return 0;
+
+       cxld = to_cxl_decoder(dev);
+       r = &cxld->hpa_range;
+
+       if (p->res && p->res->start == r->start && p->res->end == r->end)
+               return 1;
+
+       return 0;
+}
+
 static struct cxl_decoder *cxl_region_find_decoder(struct cxl_port *port,
                                                   struct cxl_region *cxlr)
 {
        struct device *dev;
        int id = 0;
 
-       dev = device_find_child(&port->dev, &id, match_free_decoder);
+       if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags))
+               dev = device_find_child(&port->dev, &cxlr->params,
+                                       match_auto_decoder);
+       else
+               dev = device_find_child(&port->dev, &id, match_free_decoder);
        if (!dev)
                return NULL;
        /*
@@ -1154,16 +1176,15 @@ static int cxl_port_setup_targets(struct cxl_port *port,
        }
 
        /*
-        * If @parent_port is masking address bits, pick the next unused address
-        * bit to route @port's targets.
+        * Interleave granularity is a multiple of @parent_port granularity.
+        * Multiplier is the parent port interleave ways.
         */
-       if (parent_iw > 1 && cxl_rr->nr_targets > 1) {
-               u32 address_bit = max(peig + peiw, eiw + peig);
-
-               eig = address_bit - eiw + 1;
-       } else {
-               eiw = peiw;
-               eig = peig;
+       rc = granularity_to_eig(parent_ig * parent_iw, &eig);
+       if (rc) {
+               dev_dbg(&cxlr->dev,
+                       "%s: invalid granularity calculation (%d * %d)\n",
+                       dev_name(&parent_port->dev), parent_ig, parent_iw);
+               return rc;
        }
 
        rc = eig_to_granularity(eig, &ig);
index 1cb1494c28fe82c36f0e75f9a1ee64f6ed77fc38..44a21ab7add51b70d17c645434934af347a93e58 100644 (file)
@@ -529,7 +529,6 @@ static int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
 
 static int cxl_pci_ras_unmask(struct pci_dev *pdev)
 {
-       struct pci_host_bridge *host_bridge = pci_find_host_bridge(pdev->bus);
        struct cxl_dev_state *cxlds = pci_get_drvdata(pdev);
        void __iomem *addr;
        u32 orig_val, val, mask;
@@ -541,9 +540,9 @@ static int cxl_pci_ras_unmask(struct pci_dev *pdev)
                return 0;
        }
 
-       /* BIOS has CXL error control */
-       if (!host_bridge->native_cxl_error)
-               return -ENXIO;
+       /* BIOS has PCIe AER error control */
+       if (!pcie_aer_is_native(pdev))
+               return 0;
 
        rc = pcie_capability_read_word(pdev, PCI_EXP_DEVCTL, &cap);
        if (rc)
index a3104e35412c150b65fb5e9c213893ad34e37e5c..aa597cda0d88741334c68bf1f9f23fcf8e43c292 100644 (file)
@@ -1211,7 +1211,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
                 * without actually having a link.
                 */
  create:
-               device = kzalloc(sizeof(*device), GFP_KERNEL);
+               device = kzalloc(sizeof(*device), GFP_ATOMIC);
                if (device == NULL)
                        break;
 
index 88466b663482f1a867c51fd103772fc06296cc27..f40c81534381219b1d968a4351391eb27ca02758 100644 (file)
@@ -101,7 +101,7 @@ static struct fw_node *fw_node_create(u32 sid, int port_count, int color)
 {
        struct fw_node *node;
 
-       node = kzalloc(struct_size(node, ports, port_count), GFP_KERNEL);
+       node = kzalloc(struct_size(node, ports, port_count), GFP_ATOMIC);
        if (node == NULL)
                return NULL;
 
index 49b70c70dc6960b79cc69e5f382a9fdd3e8b9c2e..79d4254d1f9bc537be6ad3e958928b89d40efba3 100644 (file)
@@ -1863,15 +1863,15 @@ static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp)
                return PTR_ERR(adsp2_alg);
 
        for (i = 0; i < n_algs; i++) {
-               cs_dsp_info(dsp,
-                           "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n",
-                           i, be32_to_cpu(adsp2_alg[i].alg.id),
-                           (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16,
-                           (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8,
-                           be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff,
-                           be32_to_cpu(adsp2_alg[i].xm),
-                           be32_to_cpu(adsp2_alg[i].ym),
-                           be32_to_cpu(adsp2_alg[i].zm));
+               cs_dsp_dbg(dsp,
+                          "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n",
+                          i, be32_to_cpu(adsp2_alg[i].alg.id),
+                          (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16,
+                          (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8,
+                          be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff,
+                          be32_to_cpu(adsp2_alg[i].xm),
+                          be32_to_cpu(adsp2_alg[i].ym),
+                          be32_to_cpu(adsp2_alg[i].zm));
 
                alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_XM,
                                                  adsp2_alg[i].alg.id,
@@ -1996,14 +1996,14 @@ static int cs_dsp_halo_setup_algs(struct cs_dsp *dsp)
                return PTR_ERR(halo_alg);
 
        for (i = 0; i < n_algs; i++) {
-               cs_dsp_info(dsp,
-                           "%d: ID %x v%d.%d.%d XM@%x YM@%x\n",
-                           i, be32_to_cpu(halo_alg[i].alg.id),
-                           (be32_to_cpu(halo_alg[i].alg.ver) & 0xff0000) >> 16,
-                           (be32_to_cpu(halo_alg[i].alg.ver) & 0xff00) >> 8,
-                           be32_to_cpu(halo_alg[i].alg.ver) & 0xff,
-                           be32_to_cpu(halo_alg[i].xm_base),
-                           be32_to_cpu(halo_alg[i].ym_base));
+               cs_dsp_dbg(dsp,
+                          "%d: ID %x v%d.%d.%d XM@%x YM@%x\n",
+                          i, be32_to_cpu(halo_alg[i].alg.id),
+                          (be32_to_cpu(halo_alg[i].alg.ver) & 0xff0000) >> 16,
+                          (be32_to_cpu(halo_alg[i].alg.ver) & 0xff00) >> 8,
+                          be32_to_cpu(halo_alg[i].alg.ver) & 0xff,
+                          be32_to_cpu(halo_alg[i].xm_base),
+                          be32_to_cpu(halo_alg[i].ym_base));
 
                ret = cs_dsp_halo_create_regions(dsp, halo_alg[i].alg.id,
                                                 halo_alg[i].alg.ver,
index 1599f11768426d8ff72c9c2cfc9387728af2efa3..ce20a60676f018361ee9a1a47fba0e2583e6e9a7 100644 (file)
@@ -623,6 +623,34 @@ static __init int match_config_table(const efi_guid_t *guid,
        return 0;
 }
 
+/**
+ * reserve_unaccepted - Map and reserve unaccepted configuration table
+ * @unaccepted: Pointer to unaccepted memory table
+ *
+ * memblock_add() makes sure that the table is mapped in direct mapping. During
+ * normal boot it happens automatically because the table is allocated from
+ * usable memory. But during crashkernel boot only memory specifically reserved
+ * for crash scenario is mapped. memblock_add() forces the table to be mapped
+ * in crashkernel case.
+ *
+ * Align the range to the nearest page borders. Ranges smaller than page size
+ * are not going to be mapped.
+ *
+ * memblock_reserve() makes sure that future allocations will not touch the
+ * table.
+ */
+
+static __init void reserve_unaccepted(struct efi_unaccepted_memory *unaccepted)
+{
+       phys_addr_t start, size;
+
+       start = PAGE_ALIGN_DOWN(efi.unaccepted);
+       size = PAGE_ALIGN(sizeof(*unaccepted) + unaccepted->size);
+
+       memblock_add(start, size);
+       memblock_reserve(start, size);
+}
+
 int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
                                   int count,
                                   const efi_config_table_type_t *arch_tables)
@@ -751,11 +779,9 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
 
                unaccepted = early_memremap(efi.unaccepted, sizeof(*unaccepted));
                if (unaccepted) {
-                       unsigned long size;
 
                        if (unaccepted->version == 1) {
-                               size = sizeof(*unaccepted) + unaccepted->size;
-                               memblock_reserve(efi.unaccepted, size);
+                               reserve_unaccepted(unaccepted);
                        } else {
                                efi.unaccepted = EFI_INVALID_TABLE_ADDR;
                        }
index ca61f4733ea5869356489a8f2709a23cbf591601..9a655f30ba47db013c03f2f73da88d6405507c7f 100644 (file)
@@ -62,7 +62,7 @@ efi_status_t allocate_unaccepted_bitmap(__u32 nr_desc,
        bitmap_size = DIV_ROUND_UP(unaccepted_end - unaccepted_start,
                                   EFI_UNACCEPTED_UNIT_SIZE * BITS_PER_BYTE);
 
-       status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
+       status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
                             sizeof(*unaccepted_table) + bitmap_size,
                             (void **)&unaccepted_table);
        if (status != EFI_SUCCESS) {
diff --git a/drivers/genpd/Makefile b/drivers/genpd/Makefile
deleted file mode 100644 (file)
index 6667536..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-y                                  += actions/
-obj-y                                  += amlogic/
-obj-y                                  += apple/
-obj-y                                  += bcm/
-obj-y                                  += imx/
-obj-y                                  += mediatek/
-obj-y                                  += qcom/
-obj-y                                  += renesas/
-obj-y                                  += rockchip/
-obj-y                                  += samsung/
-obj-y                                  += st/
-obj-y                                  += starfive/
-obj-y                                  += sunxi/
-obj-y                                  += tegra/
-obj-y                                  += ti/
-obj-y                                  += xilinx/
diff --git a/drivers/genpd/actions/Makefile b/drivers/genpd/actions/Makefile
deleted file mode 100644 (file)
index 7e8aa47..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0+
-obj-$(CONFIG_OWL_PM_DOMAINS_HELPER)    += owl-sps-helper.o
-obj-$(CONFIG_OWL_PM_DOMAINS)           += owl-sps.o
diff --git a/drivers/genpd/actions/owl-sps-helper.c b/drivers/genpd/actions/owl-sps-helper.c
deleted file mode 100644 (file)
index e3f3660..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Actions Semi Owl Smart Power System (SPS) shared helpers
- *
- * Copyright 2012 Actions Semi Inc.
- * Author: Actions Semi, Inc.
- *
- * Copyright (c) 2017 Andreas Färber
- */
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/soc/actions/owl-sps.h>
-
-#define OWL_SPS_PG_CTL 0x0
-
-int owl_sps_set_pg(void __iomem *base, u32 pwr_mask, u32 ack_mask, bool enable)
-{
-       u32 val;
-       bool ack;
-       int timeout;
-
-       val = readl(base + OWL_SPS_PG_CTL);
-       ack = val & ack_mask;
-       if (ack == enable)
-               return 0;
-
-       if (enable)
-               val |= pwr_mask;
-       else
-               val &= ~pwr_mask;
-
-       writel(val, base + OWL_SPS_PG_CTL);
-
-       for (timeout = 5000; timeout > 0; timeout -= 50) {
-               val = readl(base + OWL_SPS_PG_CTL);
-               if ((val & ack_mask) == (enable ? ack_mask : 0))
-                       break;
-               udelay(50);
-       }
-       if (timeout <= 0)
-               return -ETIMEDOUT;
-
-       udelay(10);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(owl_sps_set_pg);
diff --git a/drivers/genpd/actions/owl-sps.c b/drivers/genpd/actions/owl-sps.c
deleted file mode 100644 (file)
index 73a9e0b..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Actions Semi Owl Smart Power System (SPS)
- *
- * Copyright 2012 Actions Semi Inc.
- * Author: Actions Semi, Inc.
- *
- * Copyright (c) 2017 Andreas Färber
- */
-
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/pm_domain.h>
-#include <linux/soc/actions/owl-sps.h>
-#include <dt-bindings/power/owl-s500-powergate.h>
-#include <dt-bindings/power/owl-s700-powergate.h>
-#include <dt-bindings/power/owl-s900-powergate.h>
-
-struct owl_sps_domain_info {
-       const char *name;
-       int pwr_bit;
-       int ack_bit;
-       unsigned int genpd_flags;
-};
-
-struct owl_sps_info {
-       unsigned num_domains;
-       const struct owl_sps_domain_info *domains;
-};
-
-struct owl_sps {
-       struct device *dev;
-       const struct owl_sps_info *info;
-       void __iomem *base;
-       struct genpd_onecell_data genpd_data;
-       struct generic_pm_domain *domains[];
-};
-
-#define to_owl_pd(gpd) container_of(gpd, struct owl_sps_domain, genpd)
-
-struct owl_sps_domain {
-       struct generic_pm_domain genpd;
-       const struct owl_sps_domain_info *info;
-       struct owl_sps *sps;
-};
-
-static int owl_sps_set_power(struct owl_sps_domain *pd, bool enable)
-{
-       u32 pwr_mask, ack_mask;
-
-       ack_mask = BIT(pd->info->ack_bit);
-       pwr_mask = BIT(pd->info->pwr_bit);
-
-       return owl_sps_set_pg(pd->sps->base, pwr_mask, ack_mask, enable);
-}
-
-static int owl_sps_power_on(struct generic_pm_domain *domain)
-{
-       struct owl_sps_domain *pd = to_owl_pd(domain);
-
-       dev_dbg(pd->sps->dev, "%s power on", pd->info->name);
-
-       return owl_sps_set_power(pd, true);
-}
-
-static int owl_sps_power_off(struct generic_pm_domain *domain)
-{
-       struct owl_sps_domain *pd = to_owl_pd(domain);
-
-       dev_dbg(pd->sps->dev, "%s power off", pd->info->name);
-
-       return owl_sps_set_power(pd, false);
-}
-
-static int owl_sps_init_domain(struct owl_sps *sps, int index)
-{
-       struct owl_sps_domain *pd;
-
-       pd = devm_kzalloc(sps->dev, sizeof(*pd), GFP_KERNEL);
-       if (!pd)
-               return -ENOMEM;
-
-       pd->info = &sps->info->domains[index];
-       pd->sps = sps;
-
-       pd->genpd.name = pd->info->name;
-       pd->genpd.power_on = owl_sps_power_on;
-       pd->genpd.power_off = owl_sps_power_off;
-       pd->genpd.flags = pd->info->genpd_flags;
-       pm_genpd_init(&pd->genpd, NULL, false);
-
-       sps->genpd_data.domains[index] = &pd->genpd;
-
-       return 0;
-}
-
-static int owl_sps_probe(struct platform_device *pdev)
-{
-       const struct of_device_id *match;
-       const struct owl_sps_info *sps_info;
-       struct owl_sps *sps;
-       int i, ret;
-
-       if (!pdev->dev.of_node) {
-               dev_err(&pdev->dev, "no device node\n");
-               return -ENODEV;
-       }
-
-       match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
-       if (!match || !match->data) {
-               dev_err(&pdev->dev, "unknown compatible or missing data\n");
-               return -EINVAL;
-       }
-
-       sps_info = match->data;
-
-       sps = devm_kzalloc(&pdev->dev,
-                          struct_size(sps, domains, sps_info->num_domains),
-                          GFP_KERNEL);
-       if (!sps)
-               return -ENOMEM;
-
-       sps->base = of_io_request_and_map(pdev->dev.of_node, 0, "owl-sps");
-       if (IS_ERR(sps->base)) {
-               dev_err(&pdev->dev, "failed to map sps registers\n");
-               return PTR_ERR(sps->base);
-       }
-
-       sps->dev = &pdev->dev;
-       sps->info = sps_info;
-       sps->genpd_data.domains = sps->domains;
-       sps->genpd_data.num_domains = sps_info->num_domains;
-
-       for (i = 0; i < sps_info->num_domains; i++) {
-               ret = owl_sps_init_domain(sps, i);
-               if (ret)
-                       return ret;
-       }
-
-       ret = of_genpd_add_provider_onecell(pdev->dev.of_node, &sps->genpd_data);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to add provider (%d)", ret);
-               return ret;
-       }
-
-       return 0;
-}
-
-static const struct owl_sps_domain_info s500_sps_domains[] = {
-       [S500_PD_VDE] = {
-               .name = "VDE",
-               .pwr_bit = 0,
-               .ack_bit = 16,
-       },
-       [S500_PD_VCE_SI] = {
-               .name = "VCE_SI",
-               .pwr_bit = 1,
-               .ack_bit = 17,
-       },
-       [S500_PD_USB2_1] = {
-               .name = "USB2_1",
-               .pwr_bit = 2,
-               .ack_bit = 18,
-       },
-       [S500_PD_CPU2] = {
-               .name = "CPU2",
-               .pwr_bit = 5,
-               .ack_bit = 21,
-               .genpd_flags = GENPD_FLAG_ALWAYS_ON,
-       },
-       [S500_PD_CPU3] = {
-               .name = "CPU3",
-               .pwr_bit = 6,
-               .ack_bit = 22,
-               .genpd_flags = GENPD_FLAG_ALWAYS_ON,
-       },
-       [S500_PD_DMA] = {
-               .name = "DMA",
-               .pwr_bit = 8,
-               .ack_bit = 12,
-       },
-       [S500_PD_DS] = {
-               .name = "DS",
-               .pwr_bit = 9,
-               .ack_bit = 13,
-       },
-       [S500_PD_USB3] = {
-               .name = "USB3",
-               .pwr_bit = 10,
-               .ack_bit = 14,
-       },
-       [S500_PD_USB2_0] = {
-               .name = "USB2_0",
-               .pwr_bit = 11,
-               .ack_bit = 15,
-       },
-};
-
-static const struct owl_sps_info s500_sps_info = {
-       .num_domains = ARRAY_SIZE(s500_sps_domains),
-       .domains = s500_sps_domains,
-};
-
-static const struct owl_sps_domain_info s700_sps_domains[] = {
-       [S700_PD_VDE] = {
-               .name = "VDE",
-               .pwr_bit = 0,
-       },
-       [S700_PD_VCE_SI] = {
-               .name = "VCE_SI",
-               .pwr_bit = 1,
-       },
-       [S700_PD_USB2_1] = {
-               .name = "USB2_1",
-               .pwr_bit = 2,
-       },
-       [S700_PD_HDE] = {
-               .name = "HDE",
-               .pwr_bit = 7,
-       },
-       [S700_PD_DMA] = {
-               .name = "DMA",
-               .pwr_bit = 8,
-       },
-       [S700_PD_DS] = {
-               .name = "DS",
-               .pwr_bit = 9,
-       },
-       [S700_PD_USB3] = {
-               .name = "USB3",
-               .pwr_bit = 10,
-       },
-       [S700_PD_USB2_0] = {
-               .name = "USB2_0",
-               .pwr_bit = 11,
-       },
-};
-
-static const struct owl_sps_info s700_sps_info = {
-       .num_domains = ARRAY_SIZE(s700_sps_domains),
-       .domains = s700_sps_domains,
-};
-
-static const struct owl_sps_domain_info s900_sps_domains[] = {
-       [S900_PD_GPU_B] = {
-               .name = "GPU_B",
-               .pwr_bit = 3,
-       },
-       [S900_PD_VCE] = {
-               .name = "VCE",
-               .pwr_bit = 4,
-       },
-       [S900_PD_SENSOR] = {
-               .name = "SENSOR",
-               .pwr_bit = 5,
-       },
-       [S900_PD_VDE] = {
-               .name = "VDE",
-               .pwr_bit = 6,
-       },
-       [S900_PD_HDE] = {
-               .name = "HDE",
-               .pwr_bit = 7,
-       },
-       [S900_PD_USB3] = {
-               .name = "USB3",
-               .pwr_bit = 8,
-       },
-       [S900_PD_DDR0] = {
-               .name = "DDR0",
-               .pwr_bit = 9,
-       },
-       [S900_PD_DDR1] = {
-               .name = "DDR1",
-               .pwr_bit = 10,
-       },
-       [S900_PD_DE] = {
-               .name = "DE",
-               .pwr_bit = 13,
-       },
-       [S900_PD_NAND] = {
-               .name = "NAND",
-               .pwr_bit = 14,
-       },
-       [S900_PD_USB2_H0] = {
-               .name = "USB2_H0",
-               .pwr_bit = 15,
-       },
-       [S900_PD_USB2_H1] = {
-               .name = "USB2_H1",
-               .pwr_bit = 16,
-       },
-};
-
-static const struct owl_sps_info s900_sps_info = {
-       .num_domains = ARRAY_SIZE(s900_sps_domains),
-       .domains = s900_sps_domains,
-};
-
-static const struct of_device_id owl_sps_of_matches[] = {
-       { .compatible = "actions,s500-sps", .data = &s500_sps_info },
-       { .compatible = "actions,s700-sps", .data = &s700_sps_info },
-       { .compatible = "actions,s900-sps", .data = &s900_sps_info },
-       { }
-};
-
-static struct platform_driver owl_sps_platform_driver = {
-       .probe = owl_sps_probe,
-       .driver = {
-               .name = "owl-sps",
-               .of_match_table = owl_sps_of_matches,
-               .suppress_bind_attrs = true,
-       },
-};
-
-static int __init owl_sps_init(void)
-{
-       return platform_driver_register(&owl_sps_platform_driver);
-}
-postcore_initcall(owl_sps_init);
diff --git a/drivers/genpd/amlogic/Makefile b/drivers/genpd/amlogic/Makefile
deleted file mode 100644 (file)
index 3d58abd..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o
-obj-$(CONFIG_MESON_EE_PM_DOMAINS) += meson-ee-pwrc.o
-obj-$(CONFIG_MESON_SECURE_PM_DOMAINS) += meson-secure-pwrc.o
diff --git a/drivers/genpd/amlogic/meson-ee-pwrc.c b/drivers/genpd/amlogic/meson-ee-pwrc.c
deleted file mode 100644 (file)
index cfb796d..0000000
+++ /dev/null
@@ -1,635 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 2019 BayLibre, SAS
- * Author: Neil Armstrong <narmstrong@baylibre.com>
- */
-
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/bitfield.h>
-#include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
-#include <linux/of.h>
-#include <linux/reset-controller.h>
-#include <linux/reset.h>
-#include <linux/clk.h>
-#include <linux/module.h>
-#include <dt-bindings/power/meson8-power.h>
-#include <dt-bindings/power/meson-axg-power.h>
-#include <dt-bindings/power/meson-g12a-power.h>
-#include <dt-bindings/power/meson-gxbb-power.h>
-#include <dt-bindings/power/meson-sm1-power.h>
-
-/* AO Offsets */
-
-#define GX_AO_RTI_GEN_PWR_SLEEP0       (0x3a << 2)
-#define GX_AO_RTI_GEN_PWR_ISO0         (0x3b << 2)
-
-/*
- * Meson8/Meson8b/Meson8m2 only expose the power management registers of the
- * AO-bus as syscon. 0x3a from GX translates to 0x02, 0x3b translates to 0x03
- * and so on.
- */
-#define MESON8_AO_RTI_GEN_PWR_SLEEP0   (0x02 << 2)
-#define MESON8_AO_RTI_GEN_PWR_ISO0     (0x03 << 2)
-
-/* HHI Offsets */
-
-#define HHI_MEM_PD_REG0                        (0x40 << 2)
-#define HHI_VPU_MEM_PD_REG0            (0x41 << 2)
-#define HHI_VPU_MEM_PD_REG1            (0x42 << 2)
-#define HHI_VPU_MEM_PD_REG3            (0x43 << 2)
-#define HHI_VPU_MEM_PD_REG4            (0x44 << 2)
-#define HHI_AUDIO_MEM_PD_REG0          (0x45 << 2)
-#define HHI_NANOQ_MEM_PD_REG0          (0x46 << 2)
-#define HHI_NANOQ_MEM_PD_REG1          (0x47 << 2)
-#define HHI_VPU_MEM_PD_REG2            (0x4d << 2)
-
-#define G12A_HHI_NANOQ_MEM_PD_REG0     (0x43 << 2)
-#define G12A_HHI_NANOQ_MEM_PD_REG1     (0x44 << 2)
-
-struct meson_ee_pwrc;
-struct meson_ee_pwrc_domain;
-
-struct meson_ee_pwrc_mem_domain {
-       unsigned int reg;
-       unsigned int mask;
-};
-
-struct meson_ee_pwrc_top_domain {
-       unsigned int sleep_reg;
-       unsigned int sleep_mask;
-       unsigned int iso_reg;
-       unsigned int iso_mask;
-};
-
-struct meson_ee_pwrc_domain_desc {
-       char *name;
-       unsigned int reset_names_count;
-       unsigned int clk_names_count;
-       struct meson_ee_pwrc_top_domain *top_pd;
-       unsigned int mem_pd_count;
-       struct meson_ee_pwrc_mem_domain *mem_pd;
-       bool (*is_powered_off)(struct meson_ee_pwrc_domain *pwrc_domain);
-};
-
-struct meson_ee_pwrc_domain_data {
-       unsigned int count;
-       struct meson_ee_pwrc_domain_desc *domains;
-};
-
-/* TOP Power Domains */
-
-static struct meson_ee_pwrc_top_domain gx_pwrc_vpu = {
-       .sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0,
-       .sleep_mask = BIT(8),
-       .iso_reg = GX_AO_RTI_GEN_PWR_SLEEP0,
-       .iso_mask = BIT(9),
-};
-
-static struct meson_ee_pwrc_top_domain meson8_pwrc_vpu = {
-       .sleep_reg = MESON8_AO_RTI_GEN_PWR_SLEEP0,
-       .sleep_mask = BIT(8),
-       .iso_reg = MESON8_AO_RTI_GEN_PWR_SLEEP0,
-       .iso_mask = BIT(9),
-};
-
-#define SM1_EE_PD(__bit)                                       \
-       {                                                       \
-               .sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0,          \
-               .sleep_mask = BIT(__bit),                       \
-               .iso_reg = GX_AO_RTI_GEN_PWR_ISO0,              \
-               .iso_mask = BIT(__bit),                         \
-       }
-
-static struct meson_ee_pwrc_top_domain sm1_pwrc_vpu = SM1_EE_PD(8);
-static struct meson_ee_pwrc_top_domain sm1_pwrc_nna = SM1_EE_PD(16);
-static struct meson_ee_pwrc_top_domain sm1_pwrc_usb = SM1_EE_PD(17);
-static struct meson_ee_pwrc_top_domain sm1_pwrc_pci = SM1_EE_PD(18);
-static struct meson_ee_pwrc_top_domain sm1_pwrc_ge2d = SM1_EE_PD(19);
-
-static struct meson_ee_pwrc_top_domain g12a_pwrc_nna = {
-       .sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0,
-       .sleep_mask = BIT(16) | BIT(17),
-       .iso_reg = GX_AO_RTI_GEN_PWR_ISO0,
-       .iso_mask = BIT(16) | BIT(17),
-};
-
-/* Memory PD Domains */
-
-#define VPU_MEMPD(__reg)                                       \
-       { __reg, GENMASK(1, 0) },                               \
-       { __reg, GENMASK(3, 2) },                               \
-       { __reg, GENMASK(5, 4) },                               \
-       { __reg, GENMASK(7, 6) },                               \
-       { __reg, GENMASK(9, 8) },                               \
-       { __reg, GENMASK(11, 10) },                             \
-       { __reg, GENMASK(13, 12) },                             \
-       { __reg, GENMASK(15, 14) },                             \
-       { __reg, GENMASK(17, 16) },                             \
-       { __reg, GENMASK(19, 18) },                             \
-       { __reg, GENMASK(21, 20) },                             \
-       { __reg, GENMASK(23, 22) },                             \
-       { __reg, GENMASK(25, 24) },                             \
-       { __reg, GENMASK(27, 26) },                             \
-       { __reg, GENMASK(29, 28) },                             \
-       { __reg, GENMASK(31, 30) }
-
-#define VPU_HHI_MEMPD(__reg)                                   \
-       { __reg, BIT(8) },                                      \
-       { __reg, BIT(9) },                                      \
-       { __reg, BIT(10) },                                     \
-       { __reg, BIT(11) },                                     \
-       { __reg, BIT(12) },                                     \
-       { __reg, BIT(13) },                                     \
-       { __reg, BIT(14) },                                     \
-       { __reg, BIT(15) }
-
-static struct meson_ee_pwrc_mem_domain axg_pwrc_mem_vpu[] = {
-       VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
-       VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
-};
-
-static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_vpu[] = {
-       VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
-       VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
-       VPU_MEMPD(HHI_VPU_MEM_PD_REG2),
-       VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
-};
-
-static struct meson_ee_pwrc_mem_domain gxbb_pwrc_mem_vpu[] = {
-       VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
-       VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
-       VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
-};
-
-static struct meson_ee_pwrc_mem_domain meson_pwrc_mem_eth[] = {
-       { HHI_MEM_PD_REG0, GENMASK(3, 2) },
-};
-
-static struct meson_ee_pwrc_mem_domain meson8_pwrc_audio_dsp_mem[] = {
-       { HHI_MEM_PD_REG0, GENMASK(1, 0) },
-};
-
-static struct meson_ee_pwrc_mem_domain meson8_pwrc_mem_vpu[] = {
-       VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
-       VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
-       VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
-};
-
-static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_vpu[] = {
-       VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
-       VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
-       VPU_MEMPD(HHI_VPU_MEM_PD_REG2),
-       VPU_MEMPD(HHI_VPU_MEM_PD_REG3),
-       { HHI_VPU_MEM_PD_REG4, GENMASK(1, 0) },
-       { HHI_VPU_MEM_PD_REG4, GENMASK(3, 2) },
-       { HHI_VPU_MEM_PD_REG4, GENMASK(5, 4) },
-       { HHI_VPU_MEM_PD_REG4, GENMASK(7, 6) },
-       VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
-};
-
-static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_nna[] = {
-       { HHI_NANOQ_MEM_PD_REG0, 0xff },
-       { HHI_NANOQ_MEM_PD_REG1, 0xff },
-};
-
-static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_usb[] = {
-       { HHI_MEM_PD_REG0, GENMASK(31, 30) },
-};
-
-static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_pcie[] = {
-       { HHI_MEM_PD_REG0, GENMASK(29, 26) },
-};
-
-static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_ge2d[] = {
-       { HHI_MEM_PD_REG0, GENMASK(25, 18) },
-};
-
-static struct meson_ee_pwrc_mem_domain axg_pwrc_mem_audio[] = {
-       { HHI_MEM_PD_REG0, GENMASK(5, 4) },
-};
-
-static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_audio[] = {
-       { HHI_MEM_PD_REG0, GENMASK(5, 4) },
-       { HHI_AUDIO_MEM_PD_REG0, GENMASK(1, 0) },
-       { HHI_AUDIO_MEM_PD_REG0, GENMASK(3, 2) },
-       { HHI_AUDIO_MEM_PD_REG0, GENMASK(5, 4) },
-       { HHI_AUDIO_MEM_PD_REG0, GENMASK(7, 6) },
-       { HHI_AUDIO_MEM_PD_REG0, GENMASK(13, 12) },
-       { HHI_AUDIO_MEM_PD_REG0, GENMASK(15, 14) },
-       { HHI_AUDIO_MEM_PD_REG0, GENMASK(17, 16) },
-       { HHI_AUDIO_MEM_PD_REG0, GENMASK(19, 18) },
-       { HHI_AUDIO_MEM_PD_REG0, GENMASK(21, 20) },
-       { HHI_AUDIO_MEM_PD_REG0, GENMASK(23, 22) },
-       { HHI_AUDIO_MEM_PD_REG0, GENMASK(25, 24) },
-       { HHI_AUDIO_MEM_PD_REG0, GENMASK(27, 26) },
-};
-
-static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_nna[] = {
-       { G12A_HHI_NANOQ_MEM_PD_REG0, GENMASK(31, 0) },
-       { G12A_HHI_NANOQ_MEM_PD_REG1, GENMASK(23, 0) },
-};
-
-#define VPU_PD(__name, __top_pd, __mem, __is_pwr_off, __resets, __clks)        \
-       {                                                               \
-               .name = __name,                                         \
-               .reset_names_count = __resets,                          \
-               .clk_names_count = __clks,                              \
-               .top_pd = __top_pd,                                     \
-               .mem_pd_count = ARRAY_SIZE(__mem),                      \
-               .mem_pd = __mem,                                        \
-               .is_powered_off = __is_pwr_off,                         \
-       }
-
-#define TOP_PD(__name, __top_pd, __mem, __is_pwr_off)                  \
-       {                                                               \
-               .name = __name,                                         \
-               .top_pd = __top_pd,                                     \
-               .mem_pd_count = ARRAY_SIZE(__mem),                      \
-               .mem_pd = __mem,                                        \
-               .is_powered_off = __is_pwr_off,                         \
-       }
-
-#define MEM_PD(__name, __mem)                                          \
-       TOP_PD(__name, NULL, __mem, NULL)
-
-static bool pwrc_ee_is_powered_off(struct meson_ee_pwrc_domain *pwrc_domain);
-
-static struct meson_ee_pwrc_domain_desc axg_pwrc_domains[] = {
-       [PWRC_AXG_VPU_ID]  = VPU_PD("VPU", &gx_pwrc_vpu, axg_pwrc_mem_vpu,
-                                    pwrc_ee_is_powered_off, 5, 2),
-       [PWRC_AXG_ETHERNET_MEM_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
-       [PWRC_AXG_AUDIO_ID] = MEM_PD("AUDIO", axg_pwrc_mem_audio),
-};
-
-static struct meson_ee_pwrc_domain_desc g12a_pwrc_domains[] = {
-       [PWRC_G12A_VPU_ID]  = VPU_PD("VPU", &gx_pwrc_vpu, g12a_pwrc_mem_vpu,
-                                    pwrc_ee_is_powered_off, 11, 2),
-       [PWRC_G12A_ETH_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
-       [PWRC_G12A_NNA_ID] = TOP_PD("NNA", &g12a_pwrc_nna, g12a_pwrc_mem_nna,
-                                   pwrc_ee_is_powered_off),
-};
-
-static struct meson_ee_pwrc_domain_desc gxbb_pwrc_domains[] = {
-       [PWRC_GXBB_VPU_ID]  = VPU_PD("VPU", &gx_pwrc_vpu, gxbb_pwrc_mem_vpu,
-                                    pwrc_ee_is_powered_off, 12, 2),
-       [PWRC_GXBB_ETHERNET_MEM_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
-};
-
-static struct meson_ee_pwrc_domain_desc meson8_pwrc_domains[] = {
-       [PWRC_MESON8_VPU_ID]  = VPU_PD("VPU", &meson8_pwrc_vpu,
-                                      meson8_pwrc_mem_vpu,
-                                      pwrc_ee_is_powered_off, 0, 1),
-       [PWRC_MESON8_ETHERNET_MEM_ID] = MEM_PD("ETHERNET_MEM",
-                                              meson_pwrc_mem_eth),
-       [PWRC_MESON8_AUDIO_DSP_MEM_ID] = MEM_PD("AUDIO_DSP_MEM",
-                                               meson8_pwrc_audio_dsp_mem),
-};
-
-static struct meson_ee_pwrc_domain_desc meson8b_pwrc_domains[] = {
-       [PWRC_MESON8_VPU_ID]  = VPU_PD("VPU", &meson8_pwrc_vpu,
-                                      meson8_pwrc_mem_vpu,
-                                      pwrc_ee_is_powered_off, 11, 1),
-       [PWRC_MESON8_ETHERNET_MEM_ID] = MEM_PD("ETHERNET_MEM",
-                                              meson_pwrc_mem_eth),
-       [PWRC_MESON8_AUDIO_DSP_MEM_ID] = MEM_PD("AUDIO_DSP_MEM",
-                                               meson8_pwrc_audio_dsp_mem),
-};
-
-static struct meson_ee_pwrc_domain_desc sm1_pwrc_domains[] = {
-       [PWRC_SM1_VPU_ID]  = VPU_PD("VPU", &sm1_pwrc_vpu, sm1_pwrc_mem_vpu,
-                                   pwrc_ee_is_powered_off, 11, 2),
-       [PWRC_SM1_NNA_ID]  = TOP_PD("NNA", &sm1_pwrc_nna, sm1_pwrc_mem_nna,
-                                   pwrc_ee_is_powered_off),
-       [PWRC_SM1_USB_ID]  = TOP_PD("USB", &sm1_pwrc_usb, sm1_pwrc_mem_usb,
-                                   pwrc_ee_is_powered_off),
-       [PWRC_SM1_PCIE_ID] = TOP_PD("PCI", &sm1_pwrc_pci, sm1_pwrc_mem_pcie,
-                                   pwrc_ee_is_powered_off),
-       [PWRC_SM1_GE2D_ID] = TOP_PD("GE2D", &sm1_pwrc_ge2d, sm1_pwrc_mem_ge2d,
-                                   pwrc_ee_is_powered_off),
-       [PWRC_SM1_AUDIO_ID] = MEM_PD("AUDIO", sm1_pwrc_mem_audio),
-       [PWRC_SM1_ETH_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
-};
-
-struct meson_ee_pwrc_domain {
-       struct generic_pm_domain base;
-       bool enabled;
-       struct meson_ee_pwrc *pwrc;
-       struct meson_ee_pwrc_domain_desc desc;
-       struct clk_bulk_data *clks;
-       int num_clks;
-       struct reset_control *rstc;
-       int num_rstc;
-};
-
-struct meson_ee_pwrc {
-       struct regmap *regmap_ao;
-       struct regmap *regmap_hhi;
-       struct meson_ee_pwrc_domain *domains;
-       struct genpd_onecell_data xlate;
-};
-
-static bool pwrc_ee_is_powered_off(struct meson_ee_pwrc_domain *pwrc_domain)
-{
-       u32 reg;
-
-       regmap_read(pwrc_domain->pwrc->regmap_ao,
-                   pwrc_domain->desc.top_pd->sleep_reg, &reg);
-
-       return (reg & pwrc_domain->desc.top_pd->sleep_mask);
-}
-
-static int meson_ee_pwrc_off(struct generic_pm_domain *domain)
-{
-       struct meson_ee_pwrc_domain *pwrc_domain =
-               container_of(domain, struct meson_ee_pwrc_domain, base);
-       int i;
-
-       if (pwrc_domain->desc.top_pd)
-               regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
-                                  pwrc_domain->desc.top_pd->sleep_reg,
-                                  pwrc_domain->desc.top_pd->sleep_mask,
-                                  pwrc_domain->desc.top_pd->sleep_mask);
-       udelay(20);
-
-       for (i = 0 ; i < pwrc_domain->desc.mem_pd_count ; ++i)
-               regmap_update_bits(pwrc_domain->pwrc->regmap_hhi,
-                                  pwrc_domain->desc.mem_pd[i].reg,
-                                  pwrc_domain->desc.mem_pd[i].mask,
-                                  pwrc_domain->desc.mem_pd[i].mask);
-
-       udelay(20);
-
-       if (pwrc_domain->desc.top_pd)
-               regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
-                                  pwrc_domain->desc.top_pd->iso_reg,
-                                  pwrc_domain->desc.top_pd->iso_mask,
-                                  pwrc_domain->desc.top_pd->iso_mask);
-
-       if (pwrc_domain->num_clks) {
-               msleep(20);
-               clk_bulk_disable_unprepare(pwrc_domain->num_clks,
-                                          pwrc_domain->clks);
-       }
-
-       return 0;
-}
-
-static int meson_ee_pwrc_on(struct generic_pm_domain *domain)
-{
-       struct meson_ee_pwrc_domain *pwrc_domain =
-               container_of(domain, struct meson_ee_pwrc_domain, base);
-       int i, ret;
-
-       if (pwrc_domain->desc.top_pd)
-               regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
-                                  pwrc_domain->desc.top_pd->sleep_reg,
-                                  pwrc_domain->desc.top_pd->sleep_mask, 0);
-       udelay(20);
-
-       for (i = 0 ; i < pwrc_domain->desc.mem_pd_count ; ++i)
-               regmap_update_bits(pwrc_domain->pwrc->regmap_hhi,
-                                  pwrc_domain->desc.mem_pd[i].reg,
-                                  pwrc_domain->desc.mem_pd[i].mask, 0);
-
-       udelay(20);
-
-       ret = reset_control_assert(pwrc_domain->rstc);
-       if (ret)
-               return ret;
-
-       if (pwrc_domain->desc.top_pd)
-               regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
-                                  pwrc_domain->desc.top_pd->iso_reg,
-                                  pwrc_domain->desc.top_pd->iso_mask, 0);
-
-       ret = reset_control_deassert(pwrc_domain->rstc);
-       if (ret)
-               return ret;
-
-       return clk_bulk_prepare_enable(pwrc_domain->num_clks,
-                                      pwrc_domain->clks);
-}
-
-static int meson_ee_pwrc_init_domain(struct platform_device *pdev,
-                                    struct meson_ee_pwrc *pwrc,
-                                    struct meson_ee_pwrc_domain *dom)
-{
-       int ret;
-
-       dom->pwrc = pwrc;
-       dom->num_rstc = dom->desc.reset_names_count;
-       dom->num_clks = dom->desc.clk_names_count;
-
-       if (dom->num_rstc) {
-               int count = reset_control_get_count(&pdev->dev);
-
-               if (count != dom->num_rstc)
-                       dev_warn(&pdev->dev, "Invalid resets count %d for domain %s\n",
-                                count, dom->desc.name);
-
-               dom->rstc = devm_reset_control_array_get_exclusive(&pdev->dev);
-               if (IS_ERR(dom->rstc))
-                       return PTR_ERR(dom->rstc);
-       }
-
-       if (dom->num_clks) {
-               int ret = devm_clk_bulk_get_all(&pdev->dev, &dom->clks);
-               if (ret < 0)
-                       return ret;
-
-               if (dom->num_clks != ret) {
-                       dev_warn(&pdev->dev, "Invalid clocks count %d for domain %s\n",
-                                ret, dom->desc.name);
-                       dom->num_clks = ret;
-               }
-       }
-
-       dom->base.name = dom->desc.name;
-       dom->base.power_on = meson_ee_pwrc_on;
-       dom->base.power_off = meson_ee_pwrc_off;
-
-       /*
-         * TOFIX: This is a special case for the VPU power domain, which can
-        * be enabled previously by the bootloader. In this case the VPU
-         * pipeline may be functional but no driver maybe never attach
-         * to this power domain, and if the domain is disabled it could
-         * cause system errors. This is why the pm_domain_always_on_gov
-         * is used here.
-         * For the same reason, the clocks should be enabled in case
-         * we need to power the domain off, otherwise the internal clocks
-         * prepare/enable counters won't be in sync.
-         */
-       if (dom->num_clks && dom->desc.is_powered_off && !dom->desc.is_powered_off(dom)) {
-               ret = clk_bulk_prepare_enable(dom->num_clks, dom->clks);
-               if (ret)
-                       return ret;
-
-               dom->base.flags = GENPD_FLAG_ALWAYS_ON;
-               ret = pm_genpd_init(&dom->base, NULL, false);
-               if (ret)
-                       return ret;
-       } else {
-               ret = pm_genpd_init(&dom->base, NULL,
-                                   (dom->desc.is_powered_off ?
-                                    dom->desc.is_powered_off(dom) : true));
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static int meson_ee_pwrc_probe(struct platform_device *pdev)
-{
-       const struct meson_ee_pwrc_domain_data *match;
-       struct regmap *regmap_ao, *regmap_hhi;
-       struct device_node *parent_np;
-       struct meson_ee_pwrc *pwrc;
-       int i, ret;
-
-       match = of_device_get_match_data(&pdev->dev);
-       if (!match) {
-               dev_err(&pdev->dev, "failed to get match data\n");
-               return -ENODEV;
-       }
-
-       pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL);
-       if (!pwrc)
-               return -ENOMEM;
-
-       pwrc->xlate.domains = devm_kcalloc(&pdev->dev, match->count,
-                                          sizeof(*pwrc->xlate.domains),
-                                          GFP_KERNEL);
-       if (!pwrc->xlate.domains)
-               return -ENOMEM;
-
-       pwrc->domains = devm_kcalloc(&pdev->dev, match->count,
-                                    sizeof(*pwrc->domains), GFP_KERNEL);
-       if (!pwrc->domains)
-               return -ENOMEM;
-
-       pwrc->xlate.num_domains = match->count;
-
-       parent_np = of_get_parent(pdev->dev.of_node);
-       regmap_hhi = syscon_node_to_regmap(parent_np);
-       of_node_put(parent_np);
-       if (IS_ERR(regmap_hhi)) {
-               dev_err(&pdev->dev, "failed to get HHI regmap\n");
-               return PTR_ERR(regmap_hhi);
-       }
-
-       regmap_ao = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
-                                                   "amlogic,ao-sysctrl");
-       if (IS_ERR(regmap_ao)) {
-               dev_err(&pdev->dev, "failed to get AO regmap\n");
-               return PTR_ERR(regmap_ao);
-       }
-
-       pwrc->regmap_ao = regmap_ao;
-       pwrc->regmap_hhi = regmap_hhi;
-
-       platform_set_drvdata(pdev, pwrc);
-
-       for (i = 0 ; i < match->count ; ++i) {
-               struct meson_ee_pwrc_domain *dom = &pwrc->domains[i];
-
-               memcpy(&dom->desc, &match->domains[i], sizeof(dom->desc));
-
-               ret = meson_ee_pwrc_init_domain(pdev, pwrc, dom);
-               if (ret)
-                       return ret;
-
-               pwrc->xlate.domains[i] = &dom->base;
-       }
-
-       return of_genpd_add_provider_onecell(pdev->dev.of_node, &pwrc->xlate);
-}
-
-static void meson_ee_pwrc_shutdown(struct platform_device *pdev)
-{
-       struct meson_ee_pwrc *pwrc = platform_get_drvdata(pdev);
-       int i;
-
-       for (i = 0 ; i < pwrc->xlate.num_domains ; ++i) {
-               struct meson_ee_pwrc_domain *dom = &pwrc->domains[i];
-
-               if (dom->desc.is_powered_off && !dom->desc.is_powered_off(dom))
-                       meson_ee_pwrc_off(&dom->base);
-       }
-}
-
-static struct meson_ee_pwrc_domain_data meson_ee_g12a_pwrc_data = {
-       .count = ARRAY_SIZE(g12a_pwrc_domains),
-       .domains = g12a_pwrc_domains,
-};
-
-static struct meson_ee_pwrc_domain_data meson_ee_axg_pwrc_data = {
-       .count = ARRAY_SIZE(axg_pwrc_domains),
-       .domains = axg_pwrc_domains,
-};
-
-static struct meson_ee_pwrc_domain_data meson_ee_gxbb_pwrc_data = {
-       .count = ARRAY_SIZE(gxbb_pwrc_domains),
-       .domains = gxbb_pwrc_domains,
-};
-
-static struct meson_ee_pwrc_domain_data meson_ee_m8_pwrc_data = {
-       .count = ARRAY_SIZE(meson8_pwrc_domains),
-       .domains = meson8_pwrc_domains,
-};
-
-static struct meson_ee_pwrc_domain_data meson_ee_m8b_pwrc_data = {
-       .count = ARRAY_SIZE(meson8b_pwrc_domains),
-       .domains = meson8b_pwrc_domains,
-};
-
-static struct meson_ee_pwrc_domain_data meson_ee_sm1_pwrc_data = {
-       .count = ARRAY_SIZE(sm1_pwrc_domains),
-       .domains = sm1_pwrc_domains,
-};
-
-static const struct of_device_id meson_ee_pwrc_match_table[] = {
-       {
-               .compatible = "amlogic,meson8-pwrc",
-               .data = &meson_ee_m8_pwrc_data,
-       },
-       {
-               .compatible = "amlogic,meson8b-pwrc",
-               .data = &meson_ee_m8b_pwrc_data,
-       },
-       {
-               .compatible = "amlogic,meson8m2-pwrc",
-               .data = &meson_ee_m8b_pwrc_data,
-       },
-       {
-               .compatible = "amlogic,meson-axg-pwrc",
-               .data = &meson_ee_axg_pwrc_data,
-       },
-       {
-               .compatible = "amlogic,meson-gxbb-pwrc",
-               .data = &meson_ee_gxbb_pwrc_data,
-       },
-       {
-               .compatible = "amlogic,meson-g12a-pwrc",
-               .data = &meson_ee_g12a_pwrc_data,
-       },
-       {
-               .compatible = "amlogic,meson-sm1-pwrc",
-               .data = &meson_ee_sm1_pwrc_data,
-       },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, meson_ee_pwrc_match_table);
-
-static struct platform_driver meson_ee_pwrc_driver = {
-       .probe = meson_ee_pwrc_probe,
-       .shutdown = meson_ee_pwrc_shutdown,
-       .driver = {
-               .name           = "meson_ee_pwrc",
-               .of_match_table = meson_ee_pwrc_match_table,
-       },
-};
-module_platform_driver(meson_ee_pwrc_driver);
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/genpd/amlogic/meson-gx-pwrc-vpu.c b/drivers/genpd/amlogic/meson-gx-pwrc-vpu.c
deleted file mode 100644 (file)
index 33df520..0000000
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright (c) 2017 BayLibre, SAS
- * Author: Neil Armstrong <narmstrong@baylibre.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/bitfield.h>
-#include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
-#include <linux/of.h>
-#include <linux/reset.h>
-#include <linux/clk.h>
-#include <linux/module.h>
-
-/* AO Offsets */
-
-#define AO_RTI_GEN_PWR_SLEEP0          (0x3a << 2)
-
-#define GEN_PWR_VPU_HDMI               BIT(8)
-#define GEN_PWR_VPU_HDMI_ISO           BIT(9)
-
-/* HHI Offsets */
-
-#define HHI_MEM_PD_REG0                        (0x40 << 2)
-#define HHI_VPU_MEM_PD_REG0            (0x41 << 2)
-#define HHI_VPU_MEM_PD_REG1            (0x42 << 2)
-#define HHI_VPU_MEM_PD_REG2            (0x4d << 2)
-
-struct meson_gx_pwrc_vpu {
-       struct generic_pm_domain genpd;
-       struct regmap *regmap_ao;
-       struct regmap *regmap_hhi;
-       struct reset_control *rstc;
-       struct clk *vpu_clk;
-       struct clk *vapb_clk;
-};
-
-static inline
-struct meson_gx_pwrc_vpu *genpd_to_pd(struct generic_pm_domain *d)
-{
-       return container_of(d, struct meson_gx_pwrc_vpu, genpd);
-}
-
-static int meson_gx_pwrc_vpu_power_off(struct generic_pm_domain *genpd)
-{
-       struct meson_gx_pwrc_vpu *pd = genpd_to_pd(genpd);
-       int i;
-
-       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
-                          GEN_PWR_VPU_HDMI_ISO, GEN_PWR_VPU_HDMI_ISO);
-       udelay(20);
-
-       /* Power Down Memories */
-       for (i = 0; i < 32; i += 2) {
-               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0,
-                                  0x3 << i, 0x3 << i);
-               udelay(5);
-       }
-       for (i = 0; i < 32; i += 2) {
-               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1,
-                                  0x3 << i, 0x3 << i);
-               udelay(5);
-       }
-       for (i = 8; i < 16; i++) {
-               regmap_update_bits(pd->regmap_hhi, HHI_MEM_PD_REG0,
-                                  BIT(i), BIT(i));
-               udelay(5);
-       }
-       udelay(20);
-
-       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
-                          GEN_PWR_VPU_HDMI, GEN_PWR_VPU_HDMI);
-
-       msleep(20);
-
-       clk_disable_unprepare(pd->vpu_clk);
-       clk_disable_unprepare(pd->vapb_clk);
-
-       return 0;
-}
-
-static int meson_g12a_pwrc_vpu_power_off(struct generic_pm_domain *genpd)
-{
-       struct meson_gx_pwrc_vpu *pd = genpd_to_pd(genpd);
-       int i;
-
-       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
-                          GEN_PWR_VPU_HDMI_ISO, GEN_PWR_VPU_HDMI_ISO);
-       udelay(20);
-
-       /* Power Down Memories */
-       for (i = 0; i < 32; i += 2) {
-               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0,
-                                  0x3 << i, 0x3 << i);
-               udelay(5);
-       }
-       for (i = 0; i < 32; i += 2) {
-               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1,
-                                  0x3 << i, 0x3 << i);
-               udelay(5);
-       }
-       for (i = 0; i < 32; i += 2) {
-               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG2,
-                                  0x3 << i, 0x3 << i);
-               udelay(5);
-       }
-       for (i = 8; i < 16; i++) {
-               regmap_update_bits(pd->regmap_hhi, HHI_MEM_PD_REG0,
-                                  BIT(i), BIT(i));
-               udelay(5);
-       }
-       udelay(20);
-
-       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
-                          GEN_PWR_VPU_HDMI, GEN_PWR_VPU_HDMI);
-
-       msleep(20);
-
-       clk_disable_unprepare(pd->vpu_clk);
-       clk_disable_unprepare(pd->vapb_clk);
-
-       return 0;
-}
-
-static int meson_gx_pwrc_vpu_setup_clk(struct meson_gx_pwrc_vpu *pd)
-{
-       int ret;
-
-       ret = clk_prepare_enable(pd->vpu_clk);
-       if (ret)
-               return ret;
-
-       ret = clk_prepare_enable(pd->vapb_clk);
-       if (ret)
-               clk_disable_unprepare(pd->vpu_clk);
-
-       return ret;
-}
-
-static int meson_gx_pwrc_vpu_power_on(struct generic_pm_domain *genpd)
-{
-       struct meson_gx_pwrc_vpu *pd = genpd_to_pd(genpd);
-       int ret;
-       int i;
-
-       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
-                          GEN_PWR_VPU_HDMI, 0);
-       udelay(20);
-
-       /* Power Up Memories */
-       for (i = 0; i < 32; i += 2) {
-               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0,
-                                  0x3 << i, 0);
-               udelay(5);
-       }
-
-       for (i = 0; i < 32; i += 2) {
-               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1,
-                                  0x3 << i, 0);
-               udelay(5);
-       }
-
-       for (i = 8; i < 16; i++) {
-               regmap_update_bits(pd->regmap_hhi, HHI_MEM_PD_REG0,
-                                  BIT(i), 0);
-               udelay(5);
-       }
-       udelay(20);
-
-       ret = reset_control_assert(pd->rstc);
-       if (ret)
-               return ret;
-
-       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
-                          GEN_PWR_VPU_HDMI_ISO, 0);
-
-       ret = reset_control_deassert(pd->rstc);
-       if (ret)
-               return ret;
-
-       ret = meson_gx_pwrc_vpu_setup_clk(pd);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
-static int meson_g12a_pwrc_vpu_power_on(struct generic_pm_domain *genpd)
-{
-       struct meson_gx_pwrc_vpu *pd = genpd_to_pd(genpd);
-       int ret;
-       int i;
-
-       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
-                          GEN_PWR_VPU_HDMI, 0);
-       udelay(20);
-
-       /* Power Up Memories */
-       for (i = 0; i < 32; i += 2) {
-               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0,
-                                  0x3 << i, 0);
-               udelay(5);
-       }
-
-       for (i = 0; i < 32; i += 2) {
-               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1,
-                                  0x3 << i, 0);
-               udelay(5);
-       }
-
-       for (i = 0; i < 32; i += 2) {
-               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG2,
-                                  0x3 << i, 0);
-               udelay(5);
-       }
-
-       for (i = 8; i < 16; i++) {
-               regmap_update_bits(pd->regmap_hhi, HHI_MEM_PD_REG0,
-                                  BIT(i), 0);
-               udelay(5);
-       }
-       udelay(20);
-
-       ret = reset_control_assert(pd->rstc);
-       if (ret)
-               return ret;
-
-       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
-                          GEN_PWR_VPU_HDMI_ISO, 0);
-
-       ret = reset_control_deassert(pd->rstc);
-       if (ret)
-               return ret;
-
-       ret = meson_gx_pwrc_vpu_setup_clk(pd);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
-static bool meson_gx_pwrc_vpu_get_power(struct meson_gx_pwrc_vpu *pd)
-{
-       u32 reg;
-
-       regmap_read(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, &reg);
-
-       return (reg & GEN_PWR_VPU_HDMI);
-}
-
-static struct meson_gx_pwrc_vpu vpu_hdmi_pd = {
-       .genpd = {
-               .name = "vpu_hdmi",
-               .power_off = meson_gx_pwrc_vpu_power_off,
-               .power_on = meson_gx_pwrc_vpu_power_on,
-       },
-};
-
-static struct meson_gx_pwrc_vpu vpu_hdmi_pd_g12a = {
-       .genpd = {
-               .name = "vpu_hdmi",
-               .power_off = meson_g12a_pwrc_vpu_power_off,
-               .power_on = meson_g12a_pwrc_vpu_power_on,
-       },
-};
-
-static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
-{
-       const struct meson_gx_pwrc_vpu *vpu_pd_match;
-       struct regmap *regmap_ao, *regmap_hhi;
-       struct meson_gx_pwrc_vpu *vpu_pd;
-       struct device_node *parent_np;
-       struct reset_control *rstc;
-       struct clk *vpu_clk;
-       struct clk *vapb_clk;
-       bool powered_off;
-       int ret;
-
-       vpu_pd_match = of_device_get_match_data(&pdev->dev);
-       if (!vpu_pd_match) {
-               dev_err(&pdev->dev, "failed to get match data\n");
-               return -ENODEV;
-       }
-
-       vpu_pd = devm_kzalloc(&pdev->dev, sizeof(*vpu_pd), GFP_KERNEL);
-       if (!vpu_pd)
-               return -ENOMEM;
-
-       memcpy(vpu_pd, vpu_pd_match, sizeof(*vpu_pd));
-
-       parent_np = of_get_parent(pdev->dev.of_node);
-       regmap_ao = syscon_node_to_regmap(parent_np);
-       of_node_put(parent_np);
-       if (IS_ERR(regmap_ao)) {
-               dev_err(&pdev->dev, "failed to get regmap\n");
-               return PTR_ERR(regmap_ao);
-       }
-
-       regmap_hhi = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
-                                                    "amlogic,hhi-sysctrl");
-       if (IS_ERR(regmap_hhi)) {
-               dev_err(&pdev->dev, "failed to get HHI regmap\n");
-               return PTR_ERR(regmap_hhi);
-       }
-
-       rstc = devm_reset_control_array_get_exclusive(&pdev->dev);
-       if (IS_ERR(rstc))
-               return dev_err_probe(&pdev->dev, PTR_ERR(rstc),
-                                    "failed to get reset lines\n");
-
-       vpu_clk = devm_clk_get(&pdev->dev, "vpu");
-       if (IS_ERR(vpu_clk)) {
-               dev_err(&pdev->dev, "vpu clock request failed\n");
-               return PTR_ERR(vpu_clk);
-       }
-
-       vapb_clk = devm_clk_get(&pdev->dev, "vapb");
-       if (IS_ERR(vapb_clk)) {
-               dev_err(&pdev->dev, "vapb clock request failed\n");
-               return PTR_ERR(vapb_clk);
-       }
-
-       vpu_pd->regmap_ao = regmap_ao;
-       vpu_pd->regmap_hhi = regmap_hhi;
-       vpu_pd->rstc = rstc;
-       vpu_pd->vpu_clk = vpu_clk;
-       vpu_pd->vapb_clk = vapb_clk;
-
-       platform_set_drvdata(pdev, vpu_pd);
-
-       powered_off = meson_gx_pwrc_vpu_get_power(vpu_pd);
-
-       /* If already powered, sync the clock states */
-       if (!powered_off) {
-               ret = meson_gx_pwrc_vpu_setup_clk(vpu_pd);
-               if (ret)
-                       return ret;
-       }
-
-       vpu_pd->genpd.flags = GENPD_FLAG_ALWAYS_ON;
-       pm_genpd_init(&vpu_pd->genpd, NULL, powered_off);
-
-       return of_genpd_add_provider_simple(pdev->dev.of_node,
-                                           &vpu_pd->genpd);
-}
-
-static void meson_gx_pwrc_vpu_shutdown(struct platform_device *pdev)
-{
-       struct meson_gx_pwrc_vpu *vpu_pd = platform_get_drvdata(pdev);
-       bool powered_off;
-
-       powered_off = meson_gx_pwrc_vpu_get_power(vpu_pd);
-       if (!powered_off)
-               vpu_pd->genpd.power_off(&vpu_pd->genpd);
-}
-
-static const struct of_device_id meson_gx_pwrc_vpu_match_table[] = {
-       { .compatible = "amlogic,meson-gx-pwrc-vpu", .data = &vpu_hdmi_pd },
-       {
-         .compatible = "amlogic,meson-g12a-pwrc-vpu",
-         .data = &vpu_hdmi_pd_g12a
-       },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, meson_gx_pwrc_vpu_match_table);
-
-static struct platform_driver meson_gx_pwrc_vpu_driver = {
-       .probe  = meson_gx_pwrc_vpu_probe,
-       .shutdown = meson_gx_pwrc_vpu_shutdown,
-       .driver = {
-               .name           = "meson_gx_pwrc_vpu",
-               .of_match_table = meson_gx_pwrc_vpu_match_table,
-       },
-};
-module_platform_driver(meson_gx_pwrc_vpu_driver);
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/genpd/amlogic/meson-secure-pwrc.c b/drivers/genpd/amlogic/meson-secure-pwrc.c
deleted file mode 100644 (file)
index 89c881c..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Copyright (c) 2019 Amlogic, Inc.
- * Author: Jianxin Pan <jianxin.pan@amlogic.com>
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <dt-bindings/power/meson-a1-power.h>
-#include <dt-bindings/power/amlogic,c3-pwrc.h>
-#include <dt-bindings/power/meson-s4-power.h>
-#include <linux/arm-smccc.h>
-#include <linux/firmware/meson/meson_sm.h>
-#include <linux/module.h>
-
-#define PWRC_ON                1
-#define PWRC_OFF       0
-
-struct meson_secure_pwrc_domain {
-       struct generic_pm_domain base;
-       unsigned int index;
-       struct meson_secure_pwrc *pwrc;
-};
-
-struct meson_secure_pwrc {
-       struct meson_secure_pwrc_domain *domains;
-       struct genpd_onecell_data xlate;
-       struct meson_sm_firmware *fw;
-};
-
-struct meson_secure_pwrc_domain_desc {
-       unsigned int index;
-       unsigned int flags;
-       char *name;
-       bool (*is_off)(struct meson_secure_pwrc_domain *pwrc_domain);
-};
-
-struct meson_secure_pwrc_domain_data {
-       unsigned int count;
-       struct meson_secure_pwrc_domain_desc *domains;
-};
-
-static bool pwrc_secure_is_off(struct meson_secure_pwrc_domain *pwrc_domain)
-{
-       int is_off = 1;
-
-       if (meson_sm_call(pwrc_domain->pwrc->fw, SM_A1_PWRC_GET, &is_off,
-                         pwrc_domain->index, 0, 0, 0, 0) < 0)
-               pr_err("failed to get power domain status\n");
-
-       return is_off;
-}
-
-static int meson_secure_pwrc_off(struct generic_pm_domain *domain)
-{
-       int ret = 0;
-       struct meson_secure_pwrc_domain *pwrc_domain =
-               container_of(domain, struct meson_secure_pwrc_domain, base);
-
-       if (meson_sm_call(pwrc_domain->pwrc->fw, SM_A1_PWRC_SET, NULL,
-                         pwrc_domain->index, PWRC_OFF, 0, 0, 0) < 0) {
-               pr_err("failed to set power domain off\n");
-               ret = -EINVAL;
-       }
-
-       return ret;
-}
-
-static int meson_secure_pwrc_on(struct generic_pm_domain *domain)
-{
-       int ret = 0;
-       struct meson_secure_pwrc_domain *pwrc_domain =
-               container_of(domain, struct meson_secure_pwrc_domain, base);
-
-       if (meson_sm_call(pwrc_domain->pwrc->fw, SM_A1_PWRC_SET, NULL,
-                         pwrc_domain->index, PWRC_ON, 0, 0, 0) < 0) {
-               pr_err("failed to set power domain on\n");
-               ret = -EINVAL;
-       }
-
-       return ret;
-}
-
-#define SEC_PD(__name, __flag)                 \
-[PWRC_##__name##_ID] =                         \
-{                                              \
-       .name = #__name,                        \
-       .index = PWRC_##__name##_ID,            \
-       .is_off = pwrc_secure_is_off,   \
-       .flags = __flag,                        \
-}
-
-static struct meson_secure_pwrc_domain_desc a1_pwrc_domains[] = {
-       SEC_PD(DSPA,    0),
-       SEC_PD(DSPB,    0),
-       /* UART should keep working in ATF after suspend and before resume */
-       SEC_PD(UART,    GENPD_FLAG_ALWAYS_ON),
-       /* DMC is for DDR PHY ana/dig and DMC, and should be always on */
-       SEC_PD(DMC,     GENPD_FLAG_ALWAYS_ON),
-       SEC_PD(I2C,     0),
-       SEC_PD(PSRAM,   0),
-       SEC_PD(ACODEC,  0),
-       SEC_PD(AUDIO,   0),
-       SEC_PD(OTP,     0),
-       SEC_PD(DMA,     GENPD_FLAG_ALWAYS_ON | GENPD_FLAG_IRQ_SAFE),
-       SEC_PD(SD_EMMC, 0),
-       SEC_PD(RAMA,    0),
-       /* SRAMB is used as ATF runtime memory, and should be always on */
-       SEC_PD(RAMB,    GENPD_FLAG_ALWAYS_ON),
-       SEC_PD(IR,      0),
-       SEC_PD(SPICC,   0),
-       SEC_PD(SPIFC,   0),
-       SEC_PD(USB,     0),
-       /* NIC is for the Arm NIC-400 interconnect, and should be always on */
-       SEC_PD(NIC,     GENPD_FLAG_ALWAYS_ON),
-       SEC_PD(PDMIN,   0),
-       SEC_PD(RSA,     0),
-};
-
-static struct meson_secure_pwrc_domain_desc c3_pwrc_domains[] = {
-       SEC_PD(C3_NNA,  0),
-       SEC_PD(C3_AUDIO,        GENPD_FLAG_ALWAYS_ON),
-       SEC_PD(C3_SDIOA,        GENPD_FLAG_ALWAYS_ON),
-       SEC_PD(C3_EMMC, GENPD_FLAG_ALWAYS_ON),
-       SEC_PD(C3_USB_COMB, GENPD_FLAG_ALWAYS_ON),
-       SEC_PD(C3_SDCARD,       GENPD_FLAG_ALWAYS_ON),
-       SEC_PD(C3_ETH,  GENPD_FLAG_ALWAYS_ON),
-       SEC_PD(C3_GE2D, GENPD_FLAG_ALWAYS_ON),
-       SEC_PD(C3_CVE,  GENPD_FLAG_ALWAYS_ON),
-       SEC_PD(C3_GDC_WRAP,     GENPD_FLAG_ALWAYS_ON),
-       SEC_PD(C3_ISP_TOP,              GENPD_FLAG_ALWAYS_ON),
-       SEC_PD(C3_MIPI_ISP_WRAP, GENPD_FLAG_ALWAYS_ON),
-       SEC_PD(C3_VCODEC,       0),
-};
-
-static struct meson_secure_pwrc_domain_desc s4_pwrc_domains[] = {
-       SEC_PD(S4_DOS_HEVC,     0),
-       SEC_PD(S4_DOS_VDEC,     0),
-       SEC_PD(S4_VPU_HDMI,     0),
-       SEC_PD(S4_USB_COMB,     0),
-       SEC_PD(S4_GE2D,         0),
-       /* ETH is for ethernet online wakeup, and should be always on */
-       SEC_PD(S4_ETH,          GENPD_FLAG_ALWAYS_ON),
-       SEC_PD(S4_DEMOD,        0),
-       SEC_PD(S4_AUDIO,        0),
-};
-
-static int meson_secure_pwrc_probe(struct platform_device *pdev)
-{
-       int i;
-       struct device_node *sm_np;
-       struct meson_secure_pwrc *pwrc;
-       const struct meson_secure_pwrc_domain_data *match;
-
-       match = of_device_get_match_data(&pdev->dev);
-       if (!match) {
-               dev_err(&pdev->dev, "failed to get match data\n");
-               return -ENODEV;
-       }
-
-       sm_np = of_find_compatible_node(NULL, NULL, "amlogic,meson-gxbb-sm");
-       if (!sm_np) {
-               dev_err(&pdev->dev, "no secure-monitor node\n");
-               return -ENODEV;
-       }
-
-       pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL);
-       if (!pwrc) {
-               of_node_put(sm_np);
-               return -ENOMEM;
-       }
-
-       pwrc->fw = meson_sm_get(sm_np);
-       of_node_put(sm_np);
-       if (!pwrc->fw)
-               return -EPROBE_DEFER;
-
-       pwrc->xlate.domains = devm_kcalloc(&pdev->dev, match->count,
-                                          sizeof(*pwrc->xlate.domains),
-                                          GFP_KERNEL);
-       if (!pwrc->xlate.domains)
-               return -ENOMEM;
-
-       pwrc->domains = devm_kcalloc(&pdev->dev, match->count,
-                                    sizeof(*pwrc->domains), GFP_KERNEL);
-       if (!pwrc->domains)
-               return -ENOMEM;
-
-       pwrc->xlate.num_domains = match->count;
-       platform_set_drvdata(pdev, pwrc);
-
-       for (i = 0 ; i < match->count ; ++i) {
-               struct meson_secure_pwrc_domain *dom = &pwrc->domains[i];
-
-               if (!match->domains[i].name)
-                       continue;
-
-               dom->pwrc = pwrc;
-               dom->index = match->domains[i].index;
-               dom->base.name = match->domains[i].name;
-               dom->base.flags = match->domains[i].flags;
-               dom->base.power_on = meson_secure_pwrc_on;
-               dom->base.power_off = meson_secure_pwrc_off;
-
-               pm_genpd_init(&dom->base, NULL, match->domains[i].is_off(dom));
-
-               pwrc->xlate.domains[i] = &dom->base;
-       }
-
-       return of_genpd_add_provider_onecell(pdev->dev.of_node, &pwrc->xlate);
-}
-
-static struct meson_secure_pwrc_domain_data meson_secure_a1_pwrc_data = {
-       .domains = a1_pwrc_domains,
-       .count = ARRAY_SIZE(a1_pwrc_domains),
-};
-
-static struct meson_secure_pwrc_domain_data amlogic_secure_c3_pwrc_data = {
-       .domains = c3_pwrc_domains,
-       .count = ARRAY_SIZE(c3_pwrc_domains),
-};
-
-static struct meson_secure_pwrc_domain_data meson_secure_s4_pwrc_data = {
-       .domains = s4_pwrc_domains,
-       .count = ARRAY_SIZE(s4_pwrc_domains),
-};
-
-static const struct of_device_id meson_secure_pwrc_match_table[] = {
-       {
-               .compatible = "amlogic,meson-a1-pwrc",
-               .data = &meson_secure_a1_pwrc_data,
-       },
-       {
-               .compatible = "amlogic,c3-pwrc",
-               .data = &amlogic_secure_c3_pwrc_data,
-       },
-       {
-               .compatible = "amlogic,meson-s4-pwrc",
-               .data = &meson_secure_s4_pwrc_data,
-       },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, meson_secure_pwrc_match_table);
-
-static struct platform_driver meson_secure_pwrc_driver = {
-       .probe = meson_secure_pwrc_probe,
-       .driver = {
-               .name           = "meson_secure_pwrc",
-               .of_match_table = meson_secure_pwrc_match_table,
-       },
-};
-module_platform_driver(meson_secure_pwrc_driver);
-MODULE_LICENSE("Dual MIT/GPL");
diff --git a/drivers/genpd/apple/Makefile b/drivers/genpd/apple/Makefile
deleted file mode 100644 (file)
index 53665af..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_APPLE_PMGR_PWRSTATE)      += pmgr-pwrstate.o
diff --git a/drivers/genpd/apple/pmgr-pwrstate.c b/drivers/genpd/apple/pmgr-pwrstate.c
deleted file mode 100644 (file)
index d62a776..0000000
+++ /dev/null
@@ -1,326 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only OR MIT
-/*
- * Apple SoC PMGR device power state driver
- *
- * Copyright The Asahi Linux Contributors
- */
-
-#include <linux/bitops.h>
-#include <linux/bitfield.h>
-#include <linux/err.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
-#include <linux/reset-controller.h>
-#include <linux/module.h>
-
-#define APPLE_PMGR_RESET        BIT(31)
-#define APPLE_PMGR_AUTO_ENABLE  BIT(28)
-#define APPLE_PMGR_PS_AUTO      GENMASK(27, 24)
-#define APPLE_PMGR_PS_MIN       GENMASK(19, 16)
-#define APPLE_PMGR_PARENT_OFF   BIT(11)
-#define APPLE_PMGR_DEV_DISABLE  BIT(10)
-#define APPLE_PMGR_WAS_CLKGATED BIT(9)
-#define APPLE_PMGR_WAS_PWRGATED BIT(8)
-#define APPLE_PMGR_PS_ACTUAL    GENMASK(7, 4)
-#define APPLE_PMGR_PS_TARGET    GENMASK(3, 0)
-
-#define APPLE_PMGR_FLAGS        (APPLE_PMGR_WAS_CLKGATED | APPLE_PMGR_WAS_PWRGATED)
-
-#define APPLE_PMGR_PS_ACTIVE    0xf
-#define APPLE_PMGR_PS_CLKGATE   0x4
-#define APPLE_PMGR_PS_PWRGATE   0x0
-
-#define APPLE_PMGR_PS_SET_TIMEOUT 100
-#define APPLE_PMGR_RESET_TIME 1
-
-struct apple_pmgr_ps {
-       struct device *dev;
-       struct generic_pm_domain genpd;
-       struct reset_controller_dev rcdev;
-       struct regmap *regmap;
-       u32 offset;
-       u32 min_state;
-};
-
-#define genpd_to_apple_pmgr_ps(_genpd) container_of(_genpd, struct apple_pmgr_ps, genpd)
-#define rcdev_to_apple_pmgr_ps(_rcdev) container_of(_rcdev, struct apple_pmgr_ps, rcdev)
-
-static int apple_pmgr_ps_set(struct generic_pm_domain *genpd, u32 pstate, bool auto_enable)
-{
-       int ret;
-       struct apple_pmgr_ps *ps = genpd_to_apple_pmgr_ps(genpd);
-       u32 reg;
-
-       ret = regmap_read(ps->regmap, ps->offset, &reg);
-       if (ret < 0)
-               return ret;
-
-       /* Resets are synchronous, and only work if the device is powered and clocked. */
-       if (reg & APPLE_PMGR_RESET && pstate != APPLE_PMGR_PS_ACTIVE)
-               dev_err(ps->dev, "PS %s: powering off with RESET active\n",
-                       genpd->name);
-
-       reg &= ~(APPLE_PMGR_AUTO_ENABLE | APPLE_PMGR_FLAGS | APPLE_PMGR_PS_TARGET);
-       reg |= FIELD_PREP(APPLE_PMGR_PS_TARGET, pstate);
-
-       dev_dbg(ps->dev, "PS %s: pwrstate = 0x%x: 0x%x\n", genpd->name, pstate, reg);
-
-       regmap_write(ps->regmap, ps->offset, reg);
-
-       ret = regmap_read_poll_timeout_atomic(
-               ps->regmap, ps->offset, reg,
-               (FIELD_GET(APPLE_PMGR_PS_ACTUAL, reg) == pstate), 1,
-               APPLE_PMGR_PS_SET_TIMEOUT);
-       if (ret < 0)
-               dev_err(ps->dev, "PS %s: Failed to reach power state 0x%x (now: 0x%x)\n",
-                       genpd->name, pstate, reg);
-
-       if (auto_enable) {
-               /* Not all devices implement this; this is a no-op where not implemented. */
-               reg &= ~APPLE_PMGR_FLAGS;
-               reg |= APPLE_PMGR_AUTO_ENABLE;
-               regmap_write(ps->regmap, ps->offset, reg);
-       }
-
-       return ret;
-}
-
-static bool apple_pmgr_ps_is_active(struct apple_pmgr_ps *ps)
-{
-       u32 reg = 0;
-
-       regmap_read(ps->regmap, ps->offset, &reg);
-       /*
-        * We consider domains as active if they are actually on, or if they have auto-PM
-        * enabled and the intended target is on.
-        */
-       return (FIELD_GET(APPLE_PMGR_PS_ACTUAL, reg) == APPLE_PMGR_PS_ACTIVE ||
-               (FIELD_GET(APPLE_PMGR_PS_TARGET, reg) == APPLE_PMGR_PS_ACTIVE &&
-                reg & APPLE_PMGR_AUTO_ENABLE));
-}
-
-static int apple_pmgr_ps_power_on(struct generic_pm_domain *genpd)
-{
-       return apple_pmgr_ps_set(genpd, APPLE_PMGR_PS_ACTIVE, true);
-}
-
-static int apple_pmgr_ps_power_off(struct generic_pm_domain *genpd)
-{
-       return apple_pmgr_ps_set(genpd, APPLE_PMGR_PS_PWRGATE, false);
-}
-
-static int apple_pmgr_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
-{
-       struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev);
-       unsigned long flags;
-
-       spin_lock_irqsave(&ps->genpd.slock, flags);
-
-       if (ps->genpd.status == GENPD_STATE_OFF)
-               dev_err(ps->dev, "PS 0x%x: asserting RESET while powered down\n", ps->offset);
-
-       dev_dbg(ps->dev, "PS 0x%x: assert reset\n", ps->offset);
-       /* Quiesce device before asserting reset */
-       regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_DEV_DISABLE,
-                          APPLE_PMGR_DEV_DISABLE);
-       regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_RESET,
-                          APPLE_PMGR_RESET);
-
-       spin_unlock_irqrestore(&ps->genpd.slock, flags);
-
-       return 0;
-}
-
-static int apple_pmgr_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
-{
-       struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev);
-       unsigned long flags;
-
-       spin_lock_irqsave(&ps->genpd.slock, flags);
-
-       dev_dbg(ps->dev, "PS 0x%x: deassert reset\n", ps->offset);
-       regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_RESET, 0);
-       regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_DEV_DISABLE, 0);
-
-       if (ps->genpd.status == GENPD_STATE_OFF)
-               dev_err(ps->dev, "PS 0x%x: RESET was deasserted while powered down\n", ps->offset);
-
-       spin_unlock_irqrestore(&ps->genpd.slock, flags);
-
-       return 0;
-}
-
-static int apple_pmgr_reset_reset(struct reset_controller_dev *rcdev, unsigned long id)
-{
-       int ret;
-
-       ret = apple_pmgr_reset_assert(rcdev, id);
-       if (ret)
-               return ret;
-
-       usleep_range(APPLE_PMGR_RESET_TIME, 2 * APPLE_PMGR_RESET_TIME);
-
-       return apple_pmgr_reset_deassert(rcdev, id);
-}
-
-static int apple_pmgr_reset_status(struct reset_controller_dev *rcdev, unsigned long id)
-{
-       struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev);
-       u32 reg = 0;
-
-       regmap_read(ps->regmap, ps->offset, &reg);
-
-       return !!(reg & APPLE_PMGR_RESET);
-}
-
-const struct reset_control_ops apple_pmgr_reset_ops = {
-       .assert         = apple_pmgr_reset_assert,
-       .deassert       = apple_pmgr_reset_deassert,
-       .reset          = apple_pmgr_reset_reset,
-       .status         = apple_pmgr_reset_status,
-};
-
-static int apple_pmgr_reset_xlate(struct reset_controller_dev *rcdev,
-                                 const struct of_phandle_args *reset_spec)
-{
-       return 0;
-}
-
-static int apple_pmgr_ps_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *node = dev->of_node;
-       struct apple_pmgr_ps *ps;
-       struct regmap *regmap;
-       struct of_phandle_iterator it;
-       int ret;
-       const char *name;
-       bool active;
-
-       regmap = syscon_node_to_regmap(node->parent);
-       if (IS_ERR(regmap))
-               return PTR_ERR(regmap);
-
-       ps = devm_kzalloc(dev, sizeof(*ps), GFP_KERNEL);
-       if (!ps)
-               return -ENOMEM;
-
-       ps->dev = dev;
-       ps->regmap = regmap;
-
-       ret = of_property_read_string(node, "label", &name);
-       if (ret < 0) {
-               dev_err(dev, "missing label property\n");
-               return ret;
-       }
-
-       ret = of_property_read_u32(node, "reg", &ps->offset);
-       if (ret < 0) {
-               dev_err(dev, "missing reg property\n");
-               return ret;
-       }
-
-       ps->genpd.flags |= GENPD_FLAG_IRQ_SAFE;
-       ps->genpd.name = name;
-       ps->genpd.power_on = apple_pmgr_ps_power_on;
-       ps->genpd.power_off = apple_pmgr_ps_power_off;
-
-       ret = of_property_read_u32(node, "apple,min-state", &ps->min_state);
-       if (ret == 0 && ps->min_state <= APPLE_PMGR_PS_ACTIVE)
-               regmap_update_bits(regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_PS_MIN,
-                                  FIELD_PREP(APPLE_PMGR_PS_MIN, ps->min_state));
-
-       active = apple_pmgr_ps_is_active(ps);
-       if (of_property_read_bool(node, "apple,always-on")) {
-               ps->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
-               if (!active) {
-                       dev_warn(dev, "always-on domain %s is not on at boot\n", name);
-                       /* Turn it on so pm_genpd_init does not fail */
-                       active = apple_pmgr_ps_power_on(&ps->genpd) == 0;
-               }
-       }
-
-       /* Turn on auto-PM if the domain is already on */
-       if (active)
-               regmap_update_bits(regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_AUTO_ENABLE,
-                                  APPLE_PMGR_AUTO_ENABLE);
-
-       ret = pm_genpd_init(&ps->genpd, NULL, !active);
-       if (ret < 0) {
-               dev_err(dev, "pm_genpd_init failed\n");
-               return ret;
-       }
-
-       ret = of_genpd_add_provider_simple(node, &ps->genpd);
-       if (ret < 0) {
-               dev_err(dev, "of_genpd_add_provider_simple failed\n");
-               return ret;
-       }
-
-       of_for_each_phandle(&it, ret, node, "power-domains", "#power-domain-cells", -1) {
-               struct of_phandle_args parent, child;
-
-               parent.np = it.node;
-               parent.args_count = of_phandle_iterator_args(&it, parent.args, MAX_PHANDLE_ARGS);
-               child.np = node;
-               child.args_count = 0;
-               ret = of_genpd_add_subdomain(&parent, &child);
-
-               if (ret == -EPROBE_DEFER) {
-                       of_node_put(parent.np);
-                       goto err_remove;
-               } else if (ret < 0) {
-                       dev_err(dev, "failed to add to parent domain: %d (%s -> %s)\n",
-                               ret, it.node->name, node->name);
-                       of_node_put(parent.np);
-                       goto err_remove;
-               }
-       }
-
-       /*
-        * Do not participate in regular PM; parent power domains are handled via the
-        * genpd hierarchy.
-        */
-       pm_genpd_remove_device(dev);
-
-       ps->rcdev.owner = THIS_MODULE;
-       ps->rcdev.nr_resets = 1;
-       ps->rcdev.ops = &apple_pmgr_reset_ops;
-       ps->rcdev.of_node = dev->of_node;
-       ps->rcdev.of_reset_n_cells = 0;
-       ps->rcdev.of_xlate = apple_pmgr_reset_xlate;
-
-       ret = devm_reset_controller_register(dev, &ps->rcdev);
-       if (ret < 0)
-               goto err_remove;
-
-       return 0;
-err_remove:
-       of_genpd_del_provider(node);
-       pm_genpd_remove(&ps->genpd);
-       return ret;
-}
-
-static const struct of_device_id apple_pmgr_ps_of_match[] = {
-       { .compatible = "apple,pmgr-pwrstate" },
-       {}
-};
-
-MODULE_DEVICE_TABLE(of, apple_pmgr_ps_of_match);
-
-static struct platform_driver apple_pmgr_ps_driver = {
-       .probe = apple_pmgr_ps_probe,
-       .driver = {
-               .name = "apple-pmgr-pwrstate",
-               .of_match_table = apple_pmgr_ps_of_match,
-       },
-};
-
-MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
-MODULE_DESCRIPTION("PMGR power state driver for Apple SoCs");
-
-module_platform_driver(apple_pmgr_ps_driver);
diff --git a/drivers/genpd/bcm/Makefile b/drivers/genpd/bcm/Makefile
deleted file mode 100644 (file)
index 6bfbe4e..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_BCM_PMB)                  += bcm-pmb.o
-obj-$(CONFIG_BCM2835_POWER)            += bcm2835-power.o
-obj-$(CONFIG_BCM63XX_POWER)            += bcm63xx-power.o
-obj-$(CONFIG_RASPBERRYPI_POWER)                += raspberrypi-power.o
diff --git a/drivers/genpd/bcm/bcm-pmb.c b/drivers/genpd/bcm/bcm-pmb.c
deleted file mode 100644 (file)
index a72ba26..0000000
+++ /dev/null
@@ -1,363 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (c) 2013 Broadcom
- * Copyright (C) 2020 Rafał Miłecki <rafal@milecki.pl>
- */
-
-#include <dt-bindings/soc/bcm-pmb.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/reset/bcm63xx_pmb.h>
-
-#define BPCM_ID_REG                                    0x00
-#define BPCM_CAPABILITIES                              0x04
-#define  BPCM_CAP_NUM_ZONES                            0x000000ff
-#define  BPCM_CAP_SR_REG_BITS                          0x0000ff00
-#define  BPCM_CAP_PLLTYPE                              0x00030000
-#define  BPCM_CAP_UBUS                                 0x00080000
-#define BPCM_CONTROL                                   0x08
-#define BPCM_STATUS                                    0x0c
-#define BPCM_ROSC_CONTROL                              0x10
-#define BPCM_ROSC_THRESH_H                             0x14
-#define BPCM_ROSC_THRESHOLD_BCM6838                    0x14
-#define BPCM_ROSC_THRESH_S                             0x18
-#define BPCM_ROSC_COUNT_BCM6838                                0x18
-#define BPCM_ROSC_COUNT                                        0x1c
-#define BPCM_PWD_CONTROL_BCM6838                       0x1c
-#define BPCM_PWD_CONTROL                               0x20
-#define BPCM_SR_CONTROL_BCM6838                                0x20
-#define BPCM_PWD_ACCUM_CONTROL                         0x24
-#define BPCM_SR_CONTROL                                        0x28
-#define BPCM_GLOBAL_CONTROL                            0x2c
-#define BPCM_MISC_CONTROL                              0x30
-#define BPCM_MISC_CONTROL2                             0x34
-#define BPCM_SGPHY_CNTL                                        0x38
-#define BPCM_SGPHY_STATUS                              0x3c
-#define BPCM_ZONE0                                     0x40
-#define  BPCM_ZONE_CONTROL                             0x00
-#define   BPCM_ZONE_CONTROL_MANUAL_CLK_EN              0x00000001
-#define   BPCM_ZONE_CONTROL_MANUAL_RESET_CTL           0x00000002
-#define   BPCM_ZONE_CONTROL_FREQ_SCALE_USED            0x00000004      /* R/O */
-#define   BPCM_ZONE_CONTROL_DPG_CAPABLE                        0x00000008      /* R/O */
-#define   BPCM_ZONE_CONTROL_MANUAL_MEM_PWR             0x00000030
-#define   BPCM_ZONE_CONTROL_MANUAL_ISO_CTL             0x00000040
-#define   BPCM_ZONE_CONTROL_MANUAL_CTL                 0x00000080
-#define   BPCM_ZONE_CONTROL_DPG_CTL_EN                 0x00000100
-#define   BPCM_ZONE_CONTROL_PWR_DN_REQ                 0x00000200
-#define   BPCM_ZONE_CONTROL_PWR_UP_REQ                 0x00000400
-#define   BPCM_ZONE_CONTROL_MEM_PWR_CTL_EN             0x00000800
-#define   BPCM_ZONE_CONTROL_BLK_RESET_ASSERT           0x00001000
-#define   BPCM_ZONE_CONTROL_MEM_STBY                   0x00002000
-#define   BPCM_ZONE_CONTROL_RESERVED                   0x0007c000
-#define   BPCM_ZONE_CONTROL_PWR_CNTL_STATE             0x00f80000
-#define   BPCM_ZONE_CONTROL_FREQ_SCALAR_DYN_SEL                0x01000000      /* R/O */
-#define   BPCM_ZONE_CONTROL_PWR_OFF_STATE              0x02000000      /* R/O */
-#define   BPCM_ZONE_CONTROL_PWR_ON_STATE               0x04000000      /* R/O */
-#define   BPCM_ZONE_CONTROL_PWR_GOOD                   0x08000000      /* R/O */
-#define   BPCM_ZONE_CONTROL_DPG_PWR_STATE              0x10000000      /* R/O */
-#define   BPCM_ZONE_CONTROL_MEM_PWR_STATE              0x20000000      /* R/O */
-#define   BPCM_ZONE_CONTROL_ISO_STATE                  0x40000000      /* R/O */
-#define   BPCM_ZONE_CONTROL_RESET_STATE                        0x80000000      /* R/O */
-#define  BPCM_ZONE_CONFIG1                             0x04
-#define  BPCM_ZONE_CONFIG2                             0x08
-#define  BPCM_ZONE_FREQ_SCALAR_CONTROL                 0x0c
-#define  BPCM_ZONE_SIZE                                        0x10
-
-struct bcm_pmb {
-       struct device *dev;
-       void __iomem *base;
-       spinlock_t lock;
-       bool little_endian;
-       struct genpd_onecell_data genpd_onecell_data;
-};
-
-struct bcm_pmb_pd_data {
-       const char * const name;
-       int id;
-       u8 bus;
-       u8 device;
-};
-
-struct bcm_pmb_pm_domain {
-       struct bcm_pmb *pmb;
-       const struct bcm_pmb_pd_data *data;
-       struct generic_pm_domain genpd;
-};
-
-static int bcm_pmb_bpcm_read(struct bcm_pmb *pmb, int bus, u8 device,
-                            int offset, u32 *val)
-{
-       void __iomem *base = pmb->base + bus * 0x20;
-       unsigned long flags;
-       int err;
-
-       spin_lock_irqsave(&pmb->lock, flags);
-       err = bpcm_rd(base, device, offset, val);
-       spin_unlock_irqrestore(&pmb->lock, flags);
-
-       if (!err)
-               *val = pmb->little_endian ? le32_to_cpu(*val) : be32_to_cpu(*val);
-
-       return err;
-}
-
-static int bcm_pmb_bpcm_write(struct bcm_pmb *pmb, int bus, u8 device,
-                             int offset, u32 val)
-{
-       void __iomem *base = pmb->base + bus * 0x20;
-       unsigned long flags;
-       int err;
-
-       val = pmb->little_endian ? cpu_to_le32(val) : cpu_to_be32(val);
-
-       spin_lock_irqsave(&pmb->lock, flags);
-       err = bpcm_wr(base, device, offset, val);
-       spin_unlock_irqrestore(&pmb->lock, flags);
-
-       return err;
-}
-
-static int bcm_pmb_power_off_zone(struct bcm_pmb *pmb, int bus, u8 device,
-                                 int zone)
-{
-       int offset;
-       u32 val;
-       int err;
-
-       offset = BPCM_ZONE0 + zone * BPCM_ZONE_SIZE + BPCM_ZONE_CONTROL;
-
-       err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val);
-       if (err)
-               return err;
-
-       val |= BPCM_ZONE_CONTROL_PWR_DN_REQ;
-       val &= ~BPCM_ZONE_CONTROL_PWR_UP_REQ;
-
-       err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val);
-
-       return err;
-}
-
-static int bcm_pmb_power_on_zone(struct bcm_pmb *pmb, int bus, u8 device,
-                                int zone)
-{
-       int offset;
-       u32 val;
-       int err;
-
-       offset = BPCM_ZONE0 + zone * BPCM_ZONE_SIZE + BPCM_ZONE_CONTROL;
-
-       err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val);
-       if (err)
-               return err;
-
-       if (!(val & BPCM_ZONE_CONTROL_PWR_ON_STATE)) {
-               val &= ~BPCM_ZONE_CONTROL_PWR_DN_REQ;
-               val |= BPCM_ZONE_CONTROL_DPG_CTL_EN;
-               val |= BPCM_ZONE_CONTROL_PWR_UP_REQ;
-               val |= BPCM_ZONE_CONTROL_MEM_PWR_CTL_EN;
-               val |= BPCM_ZONE_CONTROL_BLK_RESET_ASSERT;
-
-               err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val);
-       }
-
-       return err;
-}
-
-static int bcm_pmb_power_off_device(struct bcm_pmb *pmb, int bus, u8 device)
-{
-       int offset;
-       u32 val;
-       int err;
-
-       /* Entire device can be powered off by powering off the 0th zone */
-       offset = BPCM_ZONE0 + BPCM_ZONE_CONTROL;
-
-       err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val);
-       if (err)
-               return err;
-
-       if (!(val & BPCM_ZONE_CONTROL_PWR_OFF_STATE)) {
-               val = BPCM_ZONE_CONTROL_PWR_DN_REQ;
-
-               err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val);
-       }
-
-       return err;
-}
-
-static int bcm_pmb_power_on_device(struct bcm_pmb *pmb, int bus, u8 device)
-{
-       u32 val;
-       int err;
-       int i;
-
-       err = bcm_pmb_bpcm_read(pmb, bus, device, BPCM_CAPABILITIES, &val);
-       if (err)
-               return err;
-
-       for (i = 0; i < (val & BPCM_CAP_NUM_ZONES); i++) {
-               err = bcm_pmb_power_on_zone(pmb, bus, device, i);
-               if (err)
-                       return err;
-       }
-
-       return err;
-}
-
-static int bcm_pmb_power_on_sata(struct bcm_pmb *pmb, int bus, u8 device)
-{
-       int err;
-
-       err = bcm_pmb_power_on_zone(pmb, bus, device, 0);
-       if (err)
-               return err;
-
-       /* Does not apply to the BCM963158 */
-       err = bcm_pmb_bpcm_write(pmb, bus, device, BPCM_MISC_CONTROL, 0);
-       if (err)
-               return err;
-
-       err = bcm_pmb_bpcm_write(pmb, bus, device, BPCM_SR_CONTROL, 0xffffffff);
-       if (err)
-               return err;
-
-       err = bcm_pmb_bpcm_write(pmb, bus, device, BPCM_SR_CONTROL, 0);
-
-       return err;
-}
-
-static int bcm_pmb_power_on(struct generic_pm_domain *genpd)
-{
-       struct bcm_pmb_pm_domain *pd = container_of(genpd, struct bcm_pmb_pm_domain, genpd);
-       const struct bcm_pmb_pd_data *data = pd->data;
-       struct bcm_pmb *pmb = pd->pmb;
-
-       switch (data->id) {
-       case BCM_PMB_PCIE0:
-       case BCM_PMB_PCIE1:
-       case BCM_PMB_PCIE2:
-               return bcm_pmb_power_on_zone(pmb, data->bus, data->device, 0);
-       case BCM_PMB_HOST_USB:
-               return bcm_pmb_power_on_device(pmb, data->bus, data->device);
-       case BCM_PMB_SATA:
-               return bcm_pmb_power_on_sata(pmb, data->bus, data->device);
-       default:
-               dev_err(pmb->dev, "unsupported device id: %d\n", data->id);
-               return -EINVAL;
-       }
-}
-
-static int bcm_pmb_power_off(struct generic_pm_domain *genpd)
-{
-       struct bcm_pmb_pm_domain *pd = container_of(genpd, struct bcm_pmb_pm_domain, genpd);
-       const struct bcm_pmb_pd_data *data = pd->data;
-       struct bcm_pmb *pmb = pd->pmb;
-
-       switch (data->id) {
-       case BCM_PMB_PCIE0:
-       case BCM_PMB_PCIE1:
-       case BCM_PMB_PCIE2:
-               return bcm_pmb_power_off_zone(pmb, data->bus, data->device, 0);
-       case BCM_PMB_HOST_USB:
-               return bcm_pmb_power_off_device(pmb, data->bus, data->device);
-       default:
-               dev_err(pmb->dev, "unsupported device id: %d\n", data->id);
-               return -EINVAL;
-       }
-}
-
-static int bcm_pmb_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       const struct bcm_pmb_pd_data *table;
-       const struct bcm_pmb_pd_data *e;
-       struct bcm_pmb *pmb;
-       int max_id;
-       int err;
-
-       pmb = devm_kzalloc(dev, sizeof(*pmb), GFP_KERNEL);
-       if (!pmb)
-               return -ENOMEM;
-
-       pmb->dev = dev;
-
-       pmb->base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(pmb->base))
-               return PTR_ERR(pmb->base);
-
-       spin_lock_init(&pmb->lock);
-
-       pmb->little_endian = !of_device_is_big_endian(dev->of_node);
-
-       table = of_device_get_match_data(dev);
-       if (!table)
-               return -EINVAL;
-
-       max_id = 0;
-       for (e = table; e->name; e++)
-               max_id = max(max_id, e->id);
-
-       pmb->genpd_onecell_data.num_domains = max_id + 1;
-       pmb->genpd_onecell_data.domains =
-               devm_kcalloc(dev, pmb->genpd_onecell_data.num_domains,
-                            sizeof(struct generic_pm_domain *), GFP_KERNEL);
-       if (!pmb->genpd_onecell_data.domains)
-               return -ENOMEM;
-
-       for (e = table; e->name; e++) {
-               struct bcm_pmb_pm_domain *pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
-
-               if (!pd)
-                       return -ENOMEM;
-
-               pd->pmb = pmb;
-               pd->data = e;
-               pd->genpd.name = e->name;
-               pd->genpd.power_on = bcm_pmb_power_on;
-               pd->genpd.power_off = bcm_pmb_power_off;
-
-               pm_genpd_init(&pd->genpd, NULL, true);
-               pmb->genpd_onecell_data.domains[e->id] = &pd->genpd;
-       }
-
-       err = of_genpd_add_provider_onecell(dev->of_node, &pmb->genpd_onecell_data);
-       if (err) {
-               dev_err(dev, "failed to add genpd provider: %d\n", err);
-               return err;
-       }
-
-       return 0;
-}
-
-static const struct bcm_pmb_pd_data bcm_pmb_bcm4908_data[] = {
-       { .name = "pcie2", .id = BCM_PMB_PCIE2, .bus = 0, .device = 2, },
-       { .name = "pcie0", .id = BCM_PMB_PCIE0, .bus = 1, .device = 14, },
-       { .name = "pcie1", .id = BCM_PMB_PCIE1, .bus = 1, .device = 15, },
-       { .name = "usb", .id = BCM_PMB_HOST_USB, .bus = 1, .device = 17, },
-       { },
-};
-
-static const struct bcm_pmb_pd_data bcm_pmb_bcm63138_data[] = {
-       { .name = "sata", .id = BCM_PMB_SATA, .bus = 0, .device = 3, },
-       { },
-};
-
-static const struct of_device_id bcm_pmb_of_match[] = {
-       { .compatible = "brcm,bcm4908-pmb", .data = &bcm_pmb_bcm4908_data, },
-       { .compatible = "brcm,bcm63138-pmb", .data = &bcm_pmb_bcm63138_data, },
-       { },
-};
-
-static struct platform_driver bcm_pmb_driver = {
-       .driver = {
-               .name = "bcm-pmb",
-               .of_match_table = bcm_pmb_of_match,
-       },
-       .probe  = bcm_pmb_probe,
-};
-
-builtin_platform_driver(bcm_pmb_driver);
diff --git a/drivers/genpd/bcm/bcm2835-power.c b/drivers/genpd/bcm/bcm2835-power.c
deleted file mode 100644 (file)
index 1a179d4..0000000
+++ /dev/null
@@ -1,713 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Power domain driver for Broadcom BCM2835
- *
- * Copyright (C) 2018 Broadcom
- */
-
-#include <dt-bindings/soc/bcm2835-pm.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/mfd/bcm2835-pm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/reset-controller.h>
-#include <linux/types.h>
-
-#define PM_GNRIC                        0x00
-#define PM_AUDIO                        0x04
-#define PM_STATUS                       0x18
-#define PM_RSTC                                0x1c
-#define PM_RSTS                                0x20
-#define PM_WDOG                                0x24
-#define PM_PADS0                       0x28
-#define PM_PADS2                       0x2c
-#define PM_PADS3                       0x30
-#define PM_PADS4                       0x34
-#define PM_PADS5                       0x38
-#define PM_PADS6                       0x3c
-#define PM_CAM0                                0x44
-#define PM_CAM0_LDOHPEN                        BIT(2)
-#define PM_CAM0_LDOLPEN                        BIT(1)
-#define PM_CAM0_CTRLEN                 BIT(0)
-
-#define PM_CAM1                                0x48
-#define PM_CAM1_LDOHPEN                        BIT(2)
-#define PM_CAM1_LDOLPEN                        BIT(1)
-#define PM_CAM1_CTRLEN                 BIT(0)
-
-#define PM_CCP2TX                      0x4c
-#define PM_CCP2TX_LDOEN                        BIT(1)
-#define PM_CCP2TX_CTRLEN               BIT(0)
-
-#define PM_DSI0                                0x50
-#define PM_DSI0_LDOHPEN                        BIT(2)
-#define PM_DSI0_LDOLPEN                        BIT(1)
-#define PM_DSI0_CTRLEN                 BIT(0)
-
-#define PM_DSI1                                0x54
-#define PM_DSI1_LDOHPEN                        BIT(2)
-#define PM_DSI1_LDOLPEN                        BIT(1)
-#define PM_DSI1_CTRLEN                 BIT(0)
-
-#define PM_HDMI                                0x58
-#define PM_HDMI_RSTDR                  BIT(19)
-#define PM_HDMI_LDOPD                  BIT(1)
-#define PM_HDMI_CTRLEN                 BIT(0)
-
-#define PM_USB                         0x5c
-/* The power gates must be enabled with this bit before enabling the LDO in the
- * USB block.
- */
-#define PM_USB_CTRLEN                  BIT(0)
-
-#define PM_PXLDO                       0x60
-#define PM_PXBG                                0x64
-#define PM_DFT                         0x68
-#define PM_SMPS                                0x6c
-#define PM_XOSC                                0x70
-#define PM_SPAREW                      0x74
-#define PM_SPARER                      0x78
-#define PM_AVS_RSTDR                   0x7c
-#define PM_AVS_STAT                    0x80
-#define PM_AVS_EVENT                   0x84
-#define PM_AVS_INTEN                   0x88
-#define PM_DUMMY                       0xfc
-
-#define PM_IMAGE                       0x108
-#define PM_GRAFX                       0x10c
-#define PM_PROC                                0x110
-#define PM_ENAB                                BIT(12)
-#define PM_ISPRSTN                     BIT(8)
-#define PM_H264RSTN                    BIT(7)
-#define PM_PERIRSTN                    BIT(6)
-#define PM_V3DRSTN                     BIT(6)
-#define PM_ISFUNC                      BIT(5)
-#define PM_MRDONE                      BIT(4)
-#define PM_MEMREP                      BIT(3)
-#define PM_ISPOW                       BIT(2)
-#define PM_POWOK                       BIT(1)
-#define PM_POWUP                       BIT(0)
-#define PM_INRUSH_SHIFT                        13
-#define PM_INRUSH_3_5_MA               0
-#define PM_INRUSH_5_MA                 1
-#define PM_INRUSH_10_MA                        2
-#define PM_INRUSH_20_MA                        3
-#define PM_INRUSH_MASK                 (3 << PM_INRUSH_SHIFT)
-
-#define PM_PASSWORD                    0x5a000000
-
-#define PM_WDOG_TIME_SET               0x000fffff
-#define PM_RSTC_WRCFG_CLR              0xffffffcf
-#define PM_RSTS_HADWRH_SET             0x00000040
-#define PM_RSTC_WRCFG_SET              0x00000030
-#define PM_RSTC_WRCFG_FULL_RESET       0x00000020
-#define PM_RSTC_RESET                  0x00000102
-
-#define PM_READ(reg) readl(power->base + (reg))
-#define PM_WRITE(reg, val) writel(PM_PASSWORD | (val), power->base + (reg))
-
-#define ASB_BRDG_VERSION                0x00
-#define ASB_CPR_CTRL                    0x04
-
-#define ASB_V3D_S_CTRL                 0x08
-#define ASB_V3D_M_CTRL                 0x0c
-#define ASB_ISP_S_CTRL                 0x10
-#define ASB_ISP_M_CTRL                 0x14
-#define ASB_H264_S_CTRL                        0x18
-#define ASB_H264_M_CTRL                        0x1c
-
-#define ASB_REQ_STOP                    BIT(0)
-#define ASB_ACK                         BIT(1)
-#define ASB_EMPTY                       BIT(2)
-#define ASB_FULL                        BIT(3)
-
-#define ASB_AXI_BRDG_ID                        0x20
-
-#define BCM2835_BRDG_ID                        0x62726467
-
-struct bcm2835_power_domain {
-       struct generic_pm_domain base;
-       struct bcm2835_power *power;
-       u32 domain;
-       struct clk *clk;
-};
-
-struct bcm2835_power {
-       struct device           *dev;
-       /* PM registers. */
-       void __iomem            *base;
-       /* AXI Async bridge registers. */
-       void __iomem            *asb;
-       /* RPiVid bridge registers. */
-       void __iomem            *rpivid_asb;
-
-       struct genpd_onecell_data pd_xlate;
-       struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
-       struct reset_controller_dev reset;
-};
-
-static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable)
-{
-       void __iomem *base = power->asb;
-       u64 start;
-       u32 val;
-
-       switch (reg) {
-       case 0:
-               return 0;
-       case ASB_V3D_S_CTRL:
-       case ASB_V3D_M_CTRL:
-               if (power->rpivid_asb)
-                       base = power->rpivid_asb;
-               break;
-       }
-
-       start = ktime_get_ns();
-
-       /* Enable the module's async AXI bridges. */
-       if (enable) {
-               val = readl(base + reg) & ~ASB_REQ_STOP;
-       } else {
-               val = readl(base + reg) | ASB_REQ_STOP;
-       }
-       writel(PM_PASSWORD | val, base + reg);
-
-       while (readl(base + reg) & ASB_ACK) {
-               cpu_relax();
-               if (ktime_get_ns() - start >= 1000)
-                       return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
-static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
-{
-       return bcm2835_asb_control(power, reg, true);
-}
-
-static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
-{
-       return bcm2835_asb_control(power, reg, false);
-}
-
-static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg)
-{
-       struct bcm2835_power *power = pd->power;
-
-       /* We don't run this on BCM2711 */
-       if (power->rpivid_asb)
-               return 0;
-
-       /* Enable functional isolation */
-       PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
-
-       /* Enable electrical isolation */
-       PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
-
-       /* Open the power switches. */
-       PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_POWUP);
-
-       return 0;
-}
-
-static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg)
-{
-       struct bcm2835_power *power = pd->power;
-       struct device *dev = power->dev;
-       u64 start;
-       int ret;
-       int inrush;
-       bool powok;
-
-       /* We don't run this on BCM2711 */
-       if (power->rpivid_asb)
-               return 0;
-
-       /* If it was already powered on by the fw, leave it that way. */
-       if (PM_READ(pm_reg) & PM_POWUP)
-               return 0;
-
-       /* Enable power.  Allowing too much current at once may result
-        * in POWOK never getting set, so start low and ramp it up as
-        * necessary to succeed.
-        */
-       powok = false;
-       for (inrush = PM_INRUSH_3_5_MA; inrush <= PM_INRUSH_20_MA; inrush++) {
-               PM_WRITE(pm_reg,
-                        (PM_READ(pm_reg) & ~PM_INRUSH_MASK) |
-                        (inrush << PM_INRUSH_SHIFT) |
-                        PM_POWUP);
-
-               start = ktime_get_ns();
-               while (!(powok = !!(PM_READ(pm_reg) & PM_POWOK))) {
-                       cpu_relax();
-                       if (ktime_get_ns() - start >= 3000)
-                               break;
-               }
-       }
-       if (!powok) {
-               dev_err(dev, "Timeout waiting for %s power OK\n",
-                       pd->base.name);
-               ret = -ETIMEDOUT;
-               goto err_disable_powup;
-       }
-
-       /* Disable electrical isolation */
-       PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISPOW);
-
-       /* Repair memory */
-       PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_MEMREP);
-       start = ktime_get_ns();
-       while (!(PM_READ(pm_reg) & PM_MRDONE)) {
-               cpu_relax();
-               if (ktime_get_ns() - start >= 1000) {
-                       dev_err(dev, "Timeout waiting for %s memory repair\n",
-                               pd->base.name);
-                       ret = -ETIMEDOUT;
-                       goto err_disable_ispow;
-               }
-       }
-
-       /* Disable functional isolation */
-       PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISFUNC);
-
-       return 0;
-
-err_disable_ispow:
-       PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
-err_disable_powup:
-       PM_WRITE(pm_reg, PM_READ(pm_reg) & ~(PM_POWUP | PM_INRUSH_MASK));
-       return ret;
-}
-
-static int bcm2835_asb_power_on(struct bcm2835_power_domain *pd,
-                               u32 pm_reg,
-                               u32 asb_m_reg,
-                               u32 asb_s_reg,
-                               u32 reset_flags)
-{
-       struct bcm2835_power *power = pd->power;
-       int ret;
-
-       ret = clk_prepare_enable(pd->clk);
-       if (ret) {
-               dev_err(power->dev, "Failed to enable clock for %s\n",
-                       pd->base.name);
-               return ret;
-       }
-
-       /* Wait 32 clocks for reset to propagate, 1 us will be enough */
-       udelay(1);
-
-       clk_disable_unprepare(pd->clk);
-
-       /* Deassert the resets. */
-       PM_WRITE(pm_reg, PM_READ(pm_reg) | reset_flags);
-
-       ret = clk_prepare_enable(pd->clk);
-       if (ret) {
-               dev_err(power->dev, "Failed to enable clock for %s\n",
-                       pd->base.name);
-               goto err_enable_resets;
-       }
-
-       ret = bcm2835_asb_enable(power, asb_m_reg);
-       if (ret) {
-               dev_err(power->dev, "Failed to enable ASB master for %s\n",
-                       pd->base.name);
-               goto err_disable_clk;
-       }
-       ret = bcm2835_asb_enable(power, asb_s_reg);
-       if (ret) {
-               dev_err(power->dev, "Failed to enable ASB slave for %s\n",
-                       pd->base.name);
-               goto err_disable_asb_master;
-       }
-
-       return 0;
-
-err_disable_asb_master:
-       bcm2835_asb_disable(power, asb_m_reg);
-err_disable_clk:
-       clk_disable_unprepare(pd->clk);
-err_enable_resets:
-       PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
-       return ret;
-}
-
-static int bcm2835_asb_power_off(struct bcm2835_power_domain *pd,
-                                u32 pm_reg,
-                                u32 asb_m_reg,
-                                u32 asb_s_reg,
-                                u32 reset_flags)
-{
-       struct bcm2835_power *power = pd->power;
-       int ret;
-
-       ret = bcm2835_asb_disable(power, asb_s_reg);
-       if (ret) {
-               dev_warn(power->dev, "Failed to disable ASB slave for %s\n",
-                        pd->base.name);
-               return ret;
-       }
-       ret = bcm2835_asb_disable(power, asb_m_reg);
-       if (ret) {
-               dev_warn(power->dev, "Failed to disable ASB master for %s\n",
-                        pd->base.name);
-               bcm2835_asb_enable(power, asb_s_reg);
-               return ret;
-       }
-
-       clk_disable_unprepare(pd->clk);
-
-       /* Assert the resets. */
-       PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
-
-       return 0;
-}
-
-static int bcm2835_power_pd_power_on(struct generic_pm_domain *domain)
-{
-       struct bcm2835_power_domain *pd =
-               container_of(domain, struct bcm2835_power_domain, base);
-       struct bcm2835_power *power = pd->power;
-
-       switch (pd->domain) {
-       case BCM2835_POWER_DOMAIN_GRAFX:
-               return bcm2835_power_power_on(pd, PM_GRAFX);
-
-       case BCM2835_POWER_DOMAIN_GRAFX_V3D:
-               return bcm2835_asb_power_on(pd, PM_GRAFX,
-                                           ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
-                                           PM_V3DRSTN);
-
-       case BCM2835_POWER_DOMAIN_IMAGE:
-               return bcm2835_power_power_on(pd, PM_IMAGE);
-
-       case BCM2835_POWER_DOMAIN_IMAGE_PERI:
-               return bcm2835_asb_power_on(pd, PM_IMAGE,
-                                           0, 0,
-                                           PM_PERIRSTN);
-
-       case BCM2835_POWER_DOMAIN_IMAGE_ISP:
-               return bcm2835_asb_power_on(pd, PM_IMAGE,
-                                           ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
-                                           PM_ISPRSTN);
-
-       case BCM2835_POWER_DOMAIN_IMAGE_H264:
-               return bcm2835_asb_power_on(pd, PM_IMAGE,
-                                           ASB_H264_M_CTRL, ASB_H264_S_CTRL,
-                                           PM_H264RSTN);
-
-       case BCM2835_POWER_DOMAIN_USB:
-               PM_WRITE(PM_USB, PM_USB_CTRLEN);
-               return 0;
-
-       case BCM2835_POWER_DOMAIN_DSI0:
-               PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
-               PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN | PM_DSI0_LDOHPEN);
-               return 0;
-
-       case BCM2835_POWER_DOMAIN_DSI1:
-               PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
-               PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN | PM_DSI1_LDOHPEN);
-               return 0;
-
-       case BCM2835_POWER_DOMAIN_CCP2TX:
-               PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
-               PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN | PM_CCP2TX_LDOEN);
-               return 0;
-
-       case BCM2835_POWER_DOMAIN_HDMI:
-               PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_RSTDR);
-               PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_CTRLEN);
-               PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_LDOPD);
-               usleep_range(100, 200);
-               PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_RSTDR);
-               return 0;
-
-       default:
-               dev_err(power->dev, "Invalid domain %d\n", pd->domain);
-               return -EINVAL;
-       }
-}
-
-static int bcm2835_power_pd_power_off(struct generic_pm_domain *domain)
-{
-       struct bcm2835_power_domain *pd =
-               container_of(domain, struct bcm2835_power_domain, base);
-       struct bcm2835_power *power = pd->power;
-
-       switch (pd->domain) {
-       case BCM2835_POWER_DOMAIN_GRAFX:
-               return bcm2835_power_power_off(pd, PM_GRAFX);
-
-       case BCM2835_POWER_DOMAIN_GRAFX_V3D:
-               return bcm2835_asb_power_off(pd, PM_GRAFX,
-                                            ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
-                                            PM_V3DRSTN);
-
-       case BCM2835_POWER_DOMAIN_IMAGE:
-               return bcm2835_power_power_off(pd, PM_IMAGE);
-
-       case BCM2835_POWER_DOMAIN_IMAGE_PERI:
-               return bcm2835_asb_power_off(pd, PM_IMAGE,
-                                            0, 0,
-                                            PM_PERIRSTN);
-
-       case BCM2835_POWER_DOMAIN_IMAGE_ISP:
-               return bcm2835_asb_power_off(pd, PM_IMAGE,
-                                            ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
-                                            PM_ISPRSTN);
-
-       case BCM2835_POWER_DOMAIN_IMAGE_H264:
-               return bcm2835_asb_power_off(pd, PM_IMAGE,
-                                            ASB_H264_M_CTRL, ASB_H264_S_CTRL,
-                                            PM_H264RSTN);
-
-       case BCM2835_POWER_DOMAIN_USB:
-               PM_WRITE(PM_USB, 0);
-               return 0;
-
-       case BCM2835_POWER_DOMAIN_DSI0:
-               PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
-               PM_WRITE(PM_DSI0, 0);
-               return 0;
-
-       case BCM2835_POWER_DOMAIN_DSI1:
-               PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
-               PM_WRITE(PM_DSI1, 0);
-               return 0;
-
-       case BCM2835_POWER_DOMAIN_CCP2TX:
-               PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
-               PM_WRITE(PM_CCP2TX, 0);
-               return 0;
-
-       case BCM2835_POWER_DOMAIN_HDMI:
-               PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_LDOPD);
-               PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_CTRLEN);
-               return 0;
-
-       default:
-               dev_err(power->dev, "Invalid domain %d\n", pd->domain);
-               return -EINVAL;
-       }
-}
-
-static int
-bcm2835_init_power_domain(struct bcm2835_power *power,
-                         int pd_xlate_index, const char *name)
-{
-       struct device *dev = power->dev;
-       struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index];
-
-       dom->clk = devm_clk_get(dev->parent, name);
-       if (IS_ERR(dom->clk)) {
-               int ret = PTR_ERR(dom->clk);
-
-               if (ret == -EPROBE_DEFER)
-                       return ret;
-
-               /* Some domains don't have a clk, so make sure that we
-                * don't deref an error pointer later.
-                */
-               dom->clk = NULL;
-       }
-
-       dom->base.name = name;
-       dom->base.power_on = bcm2835_power_pd_power_on;
-       dom->base.power_off = bcm2835_power_pd_power_off;
-
-       dom->domain = pd_xlate_index;
-       dom->power = power;
-
-       /* XXX: on/off at boot? */
-       pm_genpd_init(&dom->base, NULL, true);
-
-       power->pd_xlate.domains[pd_xlate_index] = &dom->base;
-
-       return 0;
-}
-
-/** bcm2835_reset_reset - Resets a block that has a reset line in the
- * PM block.
- *
- * The consumer of the reset controller must have the power domain up
- * -- there's no reset ability with the power domain down.  To reset
- * the sub-block, we just disable its access to memory through the
- * ASB, reset, and re-enable.
- */
-static int bcm2835_reset_reset(struct reset_controller_dev *rcdev,
-                              unsigned long id)
-{
-       struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
-                                                  reset);
-       struct bcm2835_power_domain *pd;
-       int ret;
-
-       switch (id) {
-       case BCM2835_RESET_V3D:
-               pd = &power->domains[BCM2835_POWER_DOMAIN_GRAFX_V3D];
-               break;
-       case BCM2835_RESET_H264:
-               pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_H264];
-               break;
-       case BCM2835_RESET_ISP:
-               pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_ISP];
-               break;
-       default:
-               dev_err(power->dev, "Bad reset id %ld\n", id);
-               return -EINVAL;
-       }
-
-       ret = bcm2835_power_pd_power_off(&pd->base);
-       if (ret)
-               return ret;
-
-       return bcm2835_power_pd_power_on(&pd->base);
-}
-
-static int bcm2835_reset_status(struct reset_controller_dev *rcdev,
-                               unsigned long id)
-{
-       struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
-                                                  reset);
-
-       switch (id) {
-       case BCM2835_RESET_V3D:
-               return !PM_READ(PM_GRAFX & PM_V3DRSTN);
-       case BCM2835_RESET_H264:
-               return !PM_READ(PM_IMAGE & PM_H264RSTN);
-       case BCM2835_RESET_ISP:
-               return !PM_READ(PM_IMAGE & PM_ISPRSTN);
-       default:
-               return -EINVAL;
-       }
-}
-
-static const struct reset_control_ops bcm2835_reset_ops = {
-       .reset = bcm2835_reset_reset,
-       .status = bcm2835_reset_status,
-};
-
-static const char *const power_domain_names[] = {
-       [BCM2835_POWER_DOMAIN_GRAFX] = "grafx",
-       [BCM2835_POWER_DOMAIN_GRAFX_V3D] = "v3d",
-
-       [BCM2835_POWER_DOMAIN_IMAGE] = "image",
-       [BCM2835_POWER_DOMAIN_IMAGE_PERI] = "peri_image",
-       [BCM2835_POWER_DOMAIN_IMAGE_H264] = "h264",
-       [BCM2835_POWER_DOMAIN_IMAGE_ISP] = "isp",
-
-       [BCM2835_POWER_DOMAIN_USB] = "usb",
-       [BCM2835_POWER_DOMAIN_DSI0] = "dsi0",
-       [BCM2835_POWER_DOMAIN_DSI1] = "dsi1",
-       [BCM2835_POWER_DOMAIN_CAM0] = "cam0",
-       [BCM2835_POWER_DOMAIN_CAM1] = "cam1",
-       [BCM2835_POWER_DOMAIN_CCP2TX] = "ccp2tx",
-       [BCM2835_POWER_DOMAIN_HDMI] = "hdmi",
-};
-
-static int bcm2835_power_probe(struct platform_device *pdev)
-{
-       struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
-       struct device *dev = &pdev->dev;
-       struct bcm2835_power *power;
-       static const struct {
-               int parent, child;
-       } domain_deps[] = {
-               { BCM2835_POWER_DOMAIN_GRAFX, BCM2835_POWER_DOMAIN_GRAFX_V3D },
-               { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_PERI },
-               { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_H264 },
-               { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_ISP },
-               { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_USB },
-               { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 },
-               { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 },
-       };
-       int ret = 0, i;
-       u32 id;
-
-       power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
-       if (!power)
-               return -ENOMEM;
-       platform_set_drvdata(pdev, power);
-
-       power->dev = dev;
-       power->base = pm->base;
-       power->asb = pm->asb;
-       power->rpivid_asb = pm->rpivid_asb;
-
-       id = readl(power->asb + ASB_AXI_BRDG_ID);
-       if (id != BCM2835_BRDG_ID /* "BRDG" */) {
-               dev_err(dev, "ASB register ID returned 0x%08x\n", id);
-               return -ENODEV;
-       }
-
-       if (power->rpivid_asb) {
-               id = readl(power->rpivid_asb + ASB_AXI_BRDG_ID);
-               if (id != BCM2835_BRDG_ID /* "BRDG" */) {
-                       dev_err(dev, "RPiVid ASB register ID returned 0x%08x\n",
-                                    id);
-                       return -ENODEV;
-               }
-       }
-
-       power->pd_xlate.domains = devm_kcalloc(dev,
-                                              ARRAY_SIZE(power_domain_names),
-                                              sizeof(*power->pd_xlate.domains),
-                                              GFP_KERNEL);
-       if (!power->pd_xlate.domains)
-               return -ENOMEM;
-
-       power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names);
-
-       for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) {
-               ret = bcm2835_init_power_domain(power, i, power_domain_names[i]);
-               if (ret)
-                       goto fail;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(domain_deps); i++) {
-               pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base,
-                                      &power->domains[domain_deps[i].child].base);
-       }
-
-       power->reset.owner = THIS_MODULE;
-       power->reset.nr_resets = BCM2835_RESET_COUNT;
-       power->reset.ops = &bcm2835_reset_ops;
-       power->reset.of_node = dev->parent->of_node;
-
-       ret = devm_reset_controller_register(dev, &power->reset);
-       if (ret)
-               goto fail;
-
-       of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate);
-
-       dev_info(dev, "Broadcom BCM2835 power domains driver");
-       return 0;
-
-fail:
-       for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) {
-               struct generic_pm_domain *dom = &power->domains[i].base;
-
-               if (dom->name)
-                       pm_genpd_remove(dom);
-       }
-       return ret;
-}
-
-static struct platform_driver bcm2835_power_driver = {
-       .probe          = bcm2835_power_probe,
-       .driver = {
-               .name = "bcm2835-power",
-       },
-};
-module_platform_driver(bcm2835_power_driver);
-
-MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
-MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset");
diff --git a/drivers/genpd/bcm/bcm63xx-power.c b/drivers/genpd/bcm/bcm63xx-power.c
deleted file mode 100644 (file)
index 98b0c24..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * BCM63xx Power Domain Controller Driver
- *
- * Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
- */
-
-#include <dt-bindings/soc/bcm6318-pm.h>
-#include <dt-bindings/soc/bcm6328-pm.h>
-#include <dt-bindings/soc/bcm6362-pm.h>
-#include <dt-bindings/soc/bcm63268-pm.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/of.h>
-
-struct bcm63xx_power_dev {
-       struct generic_pm_domain genpd;
-       struct bcm63xx_power *power;
-       uint32_t mask;
-};
-
-struct bcm63xx_power {
-       void __iomem *base;
-       spinlock_t lock;
-       struct bcm63xx_power_dev *dev;
-       struct genpd_onecell_data genpd_data;
-       struct generic_pm_domain **genpd;
-};
-
-struct bcm63xx_power_data {
-       const char * const name;
-       uint8_t bit;
-       unsigned int flags;
-};
-
-static int bcm63xx_power_get_state(struct bcm63xx_power_dev *pmd, bool *is_on)
-{
-       struct bcm63xx_power *power = pmd->power;
-
-       if (!pmd->mask) {
-               *is_on = false;
-               return -EINVAL;
-       }
-
-       *is_on = !(__raw_readl(power->base) & pmd->mask);
-
-       return 0;
-}
-
-static int bcm63xx_power_set_state(struct bcm63xx_power_dev *pmd, bool on)
-{
-       struct bcm63xx_power *power = pmd->power;
-       unsigned long flags;
-       uint32_t val;
-
-       if (!pmd->mask)
-               return -EINVAL;
-
-       spin_lock_irqsave(&power->lock, flags);
-       val = __raw_readl(power->base);
-       if (on)
-               val &= ~pmd->mask;
-       else
-               val |= pmd->mask;
-       __raw_writel(val, power->base);
-       spin_unlock_irqrestore(&power->lock, flags);
-
-       return 0;
-}
-
-static int bcm63xx_power_on(struct generic_pm_domain *genpd)
-{
-       struct bcm63xx_power_dev *pmd = container_of(genpd,
-               struct bcm63xx_power_dev, genpd);
-
-       return bcm63xx_power_set_state(pmd, true);
-}
-
-static int bcm63xx_power_off(struct generic_pm_domain *genpd)
-{
-       struct bcm63xx_power_dev *pmd = container_of(genpd,
-               struct bcm63xx_power_dev, genpd);
-
-       return bcm63xx_power_set_state(pmd, false);
-}
-
-static int bcm63xx_power_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       const struct bcm63xx_power_data *entry, *table;
-       struct bcm63xx_power *power;
-       unsigned int ndom;
-       uint8_t max_bit = 0;
-       int ret;
-
-       power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
-       if (!power)
-               return -ENOMEM;
-
-       power->base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(power->base))
-               return PTR_ERR(power->base);
-
-       table = of_device_get_match_data(dev);
-       if (!table)
-               return -EINVAL;
-
-       power->genpd_data.num_domains = 0;
-       ndom = 0;
-       for (entry = table; entry->name; entry++) {
-               max_bit = max(max_bit, entry->bit);
-               ndom++;
-       }
-
-       if (!ndom)
-               return -ENODEV;
-
-       power->genpd_data.num_domains = max_bit + 1;
-
-       power->dev = devm_kcalloc(dev, power->genpd_data.num_domains,
-                                 sizeof(struct bcm63xx_power_dev),
-                                 GFP_KERNEL);
-       if (!power->dev)
-               return -ENOMEM;
-
-       power->genpd = devm_kcalloc(dev, power->genpd_data.num_domains,
-                                   sizeof(struct generic_pm_domain *),
-                                   GFP_KERNEL);
-       if (!power->genpd)
-               return -ENOMEM;
-
-       power->genpd_data.domains = power->genpd;
-
-       ndom = 0;
-       for (entry = table; entry->name; entry++) {
-               struct bcm63xx_power_dev *pmd = &power->dev[ndom];
-               bool is_on;
-
-               pmd->power = power;
-               pmd->mask = BIT(entry->bit);
-               pmd->genpd.name = entry->name;
-               pmd->genpd.flags = entry->flags;
-
-               ret = bcm63xx_power_get_state(pmd, &is_on);
-               if (ret)
-                       dev_warn(dev, "unable to get current state for %s\n",
-                                pmd->genpd.name);
-
-               pmd->genpd.power_on = bcm63xx_power_on;
-               pmd->genpd.power_off = bcm63xx_power_off;
-
-               pm_genpd_init(&pmd->genpd, NULL, !is_on);
-               power->genpd[entry->bit] = &pmd->genpd;
-
-               ndom++;
-       }
-
-       spin_lock_init(&power->lock);
-
-       ret = of_genpd_add_provider_onecell(np, &power->genpd_data);
-       if (ret) {
-               dev_err(dev, "failed to register genpd driver: %d\n", ret);
-               return ret;
-       }
-
-       dev_info(dev, "registered %u power domains\n", ndom);
-
-       return 0;
-}
-
-static const struct bcm63xx_power_data bcm6318_power_domains[] = {
-       {
-               .name = "pcie",
-               .bit = BCM6318_POWER_DOMAIN_PCIE,
-       }, {
-               .name = "usb",
-               .bit = BCM6318_POWER_DOMAIN_USB,
-       }, {
-               .name = "ephy0",
-               .bit = BCM6318_POWER_DOMAIN_EPHY0,
-       }, {
-               .name = "ephy1",
-               .bit = BCM6318_POWER_DOMAIN_EPHY1,
-       }, {
-               .name = "ephy2",
-               .bit = BCM6318_POWER_DOMAIN_EPHY2,
-       }, {
-               .name = "ephy3",
-               .bit = BCM6318_POWER_DOMAIN_EPHY3,
-       }, {
-               .name = "ldo2p5",
-               .bit = BCM6318_POWER_DOMAIN_LDO2P5,
-               .flags = GENPD_FLAG_ALWAYS_ON,
-       }, {
-               .name = "ldo2p9",
-               .bit = BCM6318_POWER_DOMAIN_LDO2P9,
-               .flags = GENPD_FLAG_ALWAYS_ON,
-       }, {
-               .name = "sw1p0",
-               .bit = BCM6318_POWER_DOMAIN_SW1P0,
-               .flags = GENPD_FLAG_ALWAYS_ON,
-       }, {
-               .name = "pad",
-               .bit = BCM6318_POWER_DOMAIN_PAD,
-               .flags = GENPD_FLAG_ALWAYS_ON,
-       }, {
-               /* sentinel */
-       },
-};
-
-static const struct bcm63xx_power_data bcm6328_power_domains[] = {
-       {
-               .name = "adsl2-mips",
-               .bit = BCM6328_POWER_DOMAIN_ADSL2_MIPS,
-       }, {
-               .name = "adsl2-phy",
-               .bit = BCM6328_POWER_DOMAIN_ADSL2_PHY,
-       }, {
-               .name = "adsl2-afe",
-               .bit = BCM6328_POWER_DOMAIN_ADSL2_AFE,
-       }, {
-               .name = "sar",
-               .bit = BCM6328_POWER_DOMAIN_SAR,
-       }, {
-               .name = "pcm",
-               .bit = BCM6328_POWER_DOMAIN_PCM,
-       }, {
-               .name = "usbd",
-               .bit = BCM6328_POWER_DOMAIN_USBD,
-       }, {
-               .name = "usbh",
-               .bit = BCM6328_POWER_DOMAIN_USBH,
-       }, {
-               .name = "pcie",
-               .bit = BCM6328_POWER_DOMAIN_PCIE,
-       }, {
-               .name = "robosw",
-               .bit = BCM6328_POWER_DOMAIN_ROBOSW,
-       }, {
-               .name = "ephy",
-               .bit = BCM6328_POWER_DOMAIN_EPHY,
-       }, {
-               /* sentinel */
-       },
-};
-
-static const struct bcm63xx_power_data bcm6362_power_domains[] = {
-       {
-               .name = "sar",
-               .bit = BCM6362_POWER_DOMAIN_SAR,
-       }, {
-               .name = "ipsec",
-               .bit = BCM6362_POWER_DOMAIN_IPSEC,
-       }, {
-               .name = "mips",
-               .bit = BCM6362_POWER_DOMAIN_MIPS,
-               .flags = GENPD_FLAG_ALWAYS_ON,
-       }, {
-               .name = "dect",
-               .bit = BCM6362_POWER_DOMAIN_DECT,
-       }, {
-               .name = "usbh",
-               .bit = BCM6362_POWER_DOMAIN_USBH,
-       }, {
-               .name = "usbd",
-               .bit = BCM6362_POWER_DOMAIN_USBD,
-       }, {
-               .name = "robosw",
-               .bit = BCM6362_POWER_DOMAIN_ROBOSW,
-       }, {
-               .name = "pcm",
-               .bit = BCM6362_POWER_DOMAIN_PCM,
-       }, {
-               .name = "periph",
-               .bit = BCM6362_POWER_DOMAIN_PERIPH,
-               .flags = GENPD_FLAG_ALWAYS_ON,
-       }, {
-               .name = "adsl-phy",
-               .bit = BCM6362_POWER_DOMAIN_ADSL_PHY,
-       }, {
-               .name = "gmii-pads",
-               .bit = BCM6362_POWER_DOMAIN_GMII_PADS,
-       }, {
-               .name = "fap",
-               .bit = BCM6362_POWER_DOMAIN_FAP,
-       }, {
-               .name = "pcie",
-               .bit = BCM6362_POWER_DOMAIN_PCIE,
-       }, {
-               .name = "wlan-pads",
-               .bit = BCM6362_POWER_DOMAIN_WLAN_PADS,
-       }, {
-               /* sentinel */
-       },
-};
-
-static const struct bcm63xx_power_data bcm63268_power_domains[] = {
-       {
-               .name = "sar",
-               .bit = BCM63268_POWER_DOMAIN_SAR,
-       }, {
-               .name = "ipsec",
-               .bit = BCM63268_POWER_DOMAIN_IPSEC,
-       }, {
-               .name = "mips",
-               .bit = BCM63268_POWER_DOMAIN_MIPS,
-               .flags = GENPD_FLAG_ALWAYS_ON,
-       }, {
-               .name = "dect",
-               .bit = BCM63268_POWER_DOMAIN_DECT,
-       }, {
-               .name = "usbh",
-               .bit = BCM63268_POWER_DOMAIN_USBH,
-       }, {
-               .name = "usbd",
-               .bit = BCM63268_POWER_DOMAIN_USBD,
-       }, {
-               .name = "robosw",
-               .bit = BCM63268_POWER_DOMAIN_ROBOSW,
-       }, {
-               .name = "pcm",
-               .bit = BCM63268_POWER_DOMAIN_PCM,
-       }, {
-               .name = "periph",
-               .bit = BCM63268_POWER_DOMAIN_PERIPH,
-               .flags = GENPD_FLAG_ALWAYS_ON,
-       }, {
-               .name = "vdsl-phy",
-               .bit = BCM63268_POWER_DOMAIN_VDSL_PHY,
-       }, {
-               .name = "vdsl-mips",
-               .bit = BCM63268_POWER_DOMAIN_VDSL_MIPS,
-       }, {
-               .name = "fap",
-               .bit = BCM63268_POWER_DOMAIN_FAP,
-       }, {
-               .name = "pcie",
-               .bit = BCM63268_POWER_DOMAIN_PCIE,
-       }, {
-               .name = "wlan-pads",
-               .bit = BCM63268_POWER_DOMAIN_WLAN_PADS,
-       }, {
-               /* sentinel */
-       },
-};
-
-static const struct of_device_id bcm63xx_power_of_match[] = {
-       {
-               .compatible = "brcm,bcm6318-power-controller",
-               .data = &bcm6318_power_domains,
-       }, {
-               .compatible = "brcm,bcm6328-power-controller",
-               .data = &bcm6328_power_domains,
-       }, {
-               .compatible = "brcm,bcm6362-power-controller",
-               .data = &bcm6362_power_domains,
-       }, {
-               .compatible = "brcm,bcm63268-power-controller",
-               .data = &bcm63268_power_domains,
-       }, {
-               /* sentinel */
-       }
-};
-
-static struct platform_driver bcm63xx_power_driver = {
-       .driver = {
-               .name = "bcm63xx-power-controller",
-               .of_match_table = bcm63xx_power_of_match,
-       },
-       .probe  = bcm63xx_power_probe,
-};
-builtin_platform_driver(bcm63xx_power_driver);
diff --git a/drivers/genpd/bcm/raspberrypi-power.c b/drivers/genpd/bcm/raspberrypi-power.c
deleted file mode 100644 (file)
index 06196eb..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* (C) 2015 Pengutronix, Alexander Aring <aar@pengutronix.de>
- *
- * Authors:
- * Alexander Aring <aar@pengutronix.de>
- * Eric Anholt <eric@anholt.net>
- */
-
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <dt-bindings/power/raspberrypi-power.h>
-#include <soc/bcm2835/raspberrypi-firmware.h>
-
-/*
- * Firmware indices for the old power domains interface.  Only a few
- * of them were actually implemented.
- */
-#define RPI_OLD_POWER_DOMAIN_USB               3
-#define RPI_OLD_POWER_DOMAIN_V3D               10
-
-struct rpi_power_domain {
-       u32 domain;
-       bool enabled;
-       bool old_interface;
-       struct generic_pm_domain base;
-       struct rpi_firmware *fw;
-};
-
-struct rpi_power_domains {
-       bool has_new_interface;
-       struct genpd_onecell_data xlate;
-       struct rpi_firmware *fw;
-       struct rpi_power_domain domains[RPI_POWER_DOMAIN_COUNT];
-};
-
-/*
- * Packet definition used by RPI_FIRMWARE_SET_POWER_STATE and
- * RPI_FIRMWARE_SET_DOMAIN_STATE
- */
-struct rpi_power_domain_packet {
-       u32 domain;
-       u32 on;
-};
-
-/*
- * Asks the firmware to enable or disable power on a specific power
- * domain.
- */
-static int rpi_firmware_set_power(struct rpi_power_domain *rpi_domain, bool on)
-{
-       struct rpi_power_domain_packet packet;
-
-       packet.domain = rpi_domain->domain;
-       packet.on = on;
-       return rpi_firmware_property(rpi_domain->fw,
-                                    rpi_domain->old_interface ?
-                                    RPI_FIRMWARE_SET_POWER_STATE :
-                                    RPI_FIRMWARE_SET_DOMAIN_STATE,
-                                    &packet, sizeof(packet));
-}
-
-static int rpi_domain_off(struct generic_pm_domain *domain)
-{
-       struct rpi_power_domain *rpi_domain =
-               container_of(domain, struct rpi_power_domain, base);
-
-       return rpi_firmware_set_power(rpi_domain, false);
-}
-
-static int rpi_domain_on(struct generic_pm_domain *domain)
-{
-       struct rpi_power_domain *rpi_domain =
-               container_of(domain, struct rpi_power_domain, base);
-
-       return rpi_firmware_set_power(rpi_domain, true);
-}
-
-static void rpi_common_init_power_domain(struct rpi_power_domains *rpi_domains,
-                                        int xlate_index, const char *name)
-{
-       struct rpi_power_domain *dom = &rpi_domains->domains[xlate_index];
-
-       dom->fw = rpi_domains->fw;
-
-       dom->base.name = name;
-       dom->base.power_on = rpi_domain_on;
-       dom->base.power_off = rpi_domain_off;
-
-       /*
-        * Treat all power domains as off at boot.
-        *
-        * The firmware itself may be keeping some domains on, but
-        * from Linux's perspective all we control is the refcounts
-        * that we give to the firmware, and we can't ask the firmware
-        * to turn off something that we haven't ourselves turned on.
-        */
-       pm_genpd_init(&dom->base, NULL, true);
-
-       rpi_domains->xlate.domains[xlate_index] = &dom->base;
-}
-
-static void rpi_init_power_domain(struct rpi_power_domains *rpi_domains,
-                                 int xlate_index, const char *name)
-{
-       struct rpi_power_domain *dom = &rpi_domains->domains[xlate_index];
-
-       if (!rpi_domains->has_new_interface)
-               return;
-
-       /* The DT binding index is the firmware's domain index minus one. */
-       dom->domain = xlate_index + 1;
-
-       rpi_common_init_power_domain(rpi_domains, xlate_index, name);
-}
-
-static void rpi_init_old_power_domain(struct rpi_power_domains *rpi_domains,
-                                     int xlate_index, int domain,
-                                     const char *name)
-{
-       struct rpi_power_domain *dom = &rpi_domains->domains[xlate_index];
-
-       dom->old_interface = true;
-       dom->domain = domain;
-
-       rpi_common_init_power_domain(rpi_domains, xlate_index, name);
-}
-
-/*
- * Detects whether the firmware supports the new power domains interface.
- *
- * The firmware doesn't actually return an error on an unknown tag,
- * and just skips over it, so we do the detection by putting an
- * unexpected value in the return field and checking if it was
- * unchanged.
- */
-static bool
-rpi_has_new_domain_support(struct rpi_power_domains *rpi_domains)
-{
-       struct rpi_power_domain_packet packet;
-       int ret;
-
-       packet.domain = RPI_POWER_DOMAIN_ARM;
-       packet.on = ~0;
-
-       ret = rpi_firmware_property(rpi_domains->fw,
-                                   RPI_FIRMWARE_GET_DOMAIN_STATE,
-                                   &packet, sizeof(packet));
-
-       return ret == 0 && packet.on != ~0;
-}
-
-static int rpi_power_probe(struct platform_device *pdev)
-{
-       struct device_node *fw_np;
-       struct device *dev = &pdev->dev;
-       struct rpi_power_domains *rpi_domains;
-
-       rpi_domains = devm_kzalloc(dev, sizeof(*rpi_domains), GFP_KERNEL);
-       if (!rpi_domains)
-               return -ENOMEM;
-
-       rpi_domains->xlate.domains =
-               devm_kcalloc(dev,
-                            RPI_POWER_DOMAIN_COUNT,
-                            sizeof(*rpi_domains->xlate.domains),
-                            GFP_KERNEL);
-       if (!rpi_domains->xlate.domains)
-               return -ENOMEM;
-
-       rpi_domains->xlate.num_domains = RPI_POWER_DOMAIN_COUNT;
-
-       fw_np = of_parse_phandle(pdev->dev.of_node, "firmware", 0);
-       if (!fw_np) {
-               dev_err(&pdev->dev, "no firmware node\n");
-               return -ENODEV;
-       }
-
-       rpi_domains->fw = devm_rpi_firmware_get(&pdev->dev, fw_np);
-       of_node_put(fw_np);
-       if (!rpi_domains->fw)
-               return -EPROBE_DEFER;
-
-       rpi_domains->has_new_interface =
-               rpi_has_new_domain_support(rpi_domains);
-
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C0, "I2C0");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C1, "I2C1");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C2, "I2C2");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VIDEO_SCALER,
-                             "VIDEO_SCALER");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VPU1, "VPU1");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_HDMI, "HDMI");
-
-       /*
-        * Use the old firmware interface for USB power, so that we
-        * can turn it on even if the firmware hasn't been updated.
-        */
-       rpi_init_old_power_domain(rpi_domains, RPI_POWER_DOMAIN_USB,
-                                 RPI_OLD_POWER_DOMAIN_USB, "USB");
-
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VEC, "VEC");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_JPEG, "JPEG");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_H264, "H264");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_V3D, "V3D");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_ISP, "ISP");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_UNICAM0, "UNICAM0");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_UNICAM1, "UNICAM1");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CCP2RX, "CCP2RX");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CSI2, "CSI2");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CPI, "CPI");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_DSI0, "DSI0");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_DSI1, "DSI1");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_TRANSPOSER,
-                             "TRANSPOSER");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CCP2TX, "CCP2TX");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CDP, "CDP");
-       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_ARM, "ARM");
-
-       of_genpd_add_provider_onecell(dev->of_node, &rpi_domains->xlate);
-
-       platform_set_drvdata(pdev, rpi_domains);
-
-       return 0;
-}
-
-static const struct of_device_id rpi_power_of_match[] = {
-       { .compatible = "raspberrypi,bcm2835-power", },
-       {},
-};
-MODULE_DEVICE_TABLE(of, rpi_power_of_match);
-
-static struct platform_driver rpi_power_driver = {
-       .driver = {
-               .name = "raspberrypi-power",
-               .of_match_table = rpi_power_of_match,
-       },
-       .probe          = rpi_power_probe,
-};
-builtin_platform_driver(rpi_power_driver);
-
-MODULE_AUTHOR("Alexander Aring <aar@pengutronix.de>");
-MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
-MODULE_DESCRIPTION("Raspberry Pi power domain driver");
diff --git a/drivers/genpd/imx/Makefile b/drivers/genpd/imx/Makefile
deleted file mode 100644 (file)
index 52d2629..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
-obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
-obj-$(CONFIG_IMX_SCU_PD) += scu-pd.o
-obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8m-blk-ctrl.o
-obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8mp-blk-ctrl.o
-obj-$(CONFIG_SOC_IMX9) += imx93-pd.o
-obj-$(CONFIG_IMX9_BLK_CTRL) += imx93-blk-ctrl.o
diff --git a/drivers/genpd/imx/gpc.c b/drivers/genpd/imx/gpc.c
deleted file mode 100644 (file)
index 90a8b2c..0000000
+++ /dev/null
@@ -1,554 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
- * Copyright 2011-2013 Freescale Semiconductor, Inc.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/regmap.h>
-#include <linux/regulator/consumer.h>
-
-#define GPC_CNTR               0x000
-
-#define GPC_PGC_CTRL_OFFS      0x0
-#define GPC_PGC_PUPSCR_OFFS    0x4
-#define GPC_PGC_PDNSCR_OFFS    0x8
-#define GPC_PGC_SW2ISO_SHIFT   0x8
-#define GPC_PGC_SW_SHIFT       0x0
-
-#define GPC_PGC_PCI_PDN                0x200
-#define GPC_PGC_PCI_SR         0x20c
-
-#define GPC_PGC_GPU_PDN                0x260
-#define GPC_PGC_GPU_PUPSCR     0x264
-#define GPC_PGC_GPU_PDNSCR     0x268
-#define GPC_PGC_GPU_SR         0x26c
-
-#define GPC_PGC_DISP_PDN       0x240
-#define GPC_PGC_DISP_SR                0x24c
-
-#define GPU_VPU_PUP_REQ                BIT(1)
-#define GPU_VPU_PDN_REQ                BIT(0)
-
-#define GPC_CLK_MAX            7
-
-#define PGC_DOMAIN_FLAG_NO_PD          BIT(0)
-
-struct imx_pm_domain {
-       struct generic_pm_domain base;
-       struct regmap *regmap;
-       struct regulator *supply;
-       struct clk *clk[GPC_CLK_MAX];
-       int num_clks;
-       unsigned int reg_offs;
-       signed char cntr_pdn_bit;
-       unsigned int ipg_rate_mhz;
-};
-
-static inline struct imx_pm_domain *
-to_imx_pm_domain(struct generic_pm_domain *genpd)
-{
-       return container_of(genpd, struct imx_pm_domain, base);
-}
-
-static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd)
-{
-       struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
-       int iso, iso2sw;
-       u32 val;
-
-       /* Read ISO and ISO2SW power down delays */
-       regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PDNSCR_OFFS, &val);
-       iso = val & 0x3f;
-       iso2sw = (val >> 8) & 0x3f;
-
-       /* Gate off domain when powered down */
-       regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
-                          0x1, 0x1);
-
-       /* Request GPC to power down domain */
-       val = BIT(pd->cntr_pdn_bit);
-       regmap_update_bits(pd->regmap, GPC_CNTR, val, val);
-
-       /* Wait ISO + ISO2SW IPG clock cycles */
-       udelay(DIV_ROUND_UP(iso + iso2sw, pd->ipg_rate_mhz));
-
-       if (pd->supply)
-               regulator_disable(pd->supply);
-
-       return 0;
-}
-
-static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd)
-{
-       struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
-       int i, ret;
-       u32 val, req;
-
-       if (pd->supply) {
-               ret = regulator_enable(pd->supply);
-               if (ret) {
-                       pr_err("%s: failed to enable regulator: %d\n",
-                              __func__, ret);
-                       return ret;
-               }
-       }
-
-       /* Enable reset clocks for all devices in the domain */
-       for (i = 0; i < pd->num_clks; i++)
-               clk_prepare_enable(pd->clk[i]);
-
-       /* Gate off domain when powered down */
-       regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
-                          0x1, 0x1);
-
-       /* Request GPC to power up domain */
-       req = BIT(pd->cntr_pdn_bit + 1);
-       regmap_update_bits(pd->regmap, GPC_CNTR, req, req);
-
-       /* Wait for the PGC to handle the request */
-       ret = regmap_read_poll_timeout(pd->regmap, GPC_CNTR, val, !(val & req),
-                                      1, 50);
-       if (ret)
-               pr_err("powerup request on domain %s timed out\n", genpd->name);
-
-       /* Wait for reset to propagate through peripherals */
-       usleep_range(5, 10);
-
-       /* Disable reset clocks for all devices in the domain */
-       for (i = 0; i < pd->num_clks; i++)
-               clk_disable_unprepare(pd->clk[i]);
-
-       return 0;
-}
-
-static int imx_pgc_get_clocks(struct device *dev, struct imx_pm_domain *domain)
-{
-       int i, ret;
-
-       for (i = 0; ; i++) {
-               struct clk *clk = of_clk_get(dev->of_node, i);
-               if (IS_ERR(clk))
-                       break;
-               if (i >= GPC_CLK_MAX) {
-                       dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX);
-                       ret = -EINVAL;
-                       goto clk_err;
-               }
-               domain->clk[i] = clk;
-       }
-       domain->num_clks = i;
-
-       return 0;
-
-clk_err:
-       while (i--)
-               clk_put(domain->clk[i]);
-
-       return ret;
-}
-
-static void imx_pgc_put_clocks(struct imx_pm_domain *domain)
-{
-       int i;
-
-       for (i = domain->num_clks - 1; i >= 0; i--)
-               clk_put(domain->clk[i]);
-}
-
-static int imx_pgc_parse_dt(struct device *dev, struct imx_pm_domain *domain)
-{
-       /* try to get the domain supply regulator */
-       domain->supply = devm_regulator_get_optional(dev, "power");
-       if (IS_ERR(domain->supply)) {
-               if (PTR_ERR(domain->supply) == -ENODEV)
-                       domain->supply = NULL;
-               else
-                       return PTR_ERR(domain->supply);
-       }
-
-       /* try to get all clocks needed for reset propagation */
-       return imx_pgc_get_clocks(dev, domain);
-}
-
-static int imx_pgc_power_domain_probe(struct platform_device *pdev)
-{
-       struct imx_pm_domain *domain = pdev->dev.platform_data;
-       struct device *dev = &pdev->dev;
-       int ret;
-
-       /* if this PD is associated with a DT node try to parse it */
-       if (dev->of_node) {
-               ret = imx_pgc_parse_dt(dev, domain);
-               if (ret)
-                       return ret;
-       }
-
-       /* initially power on the domain */
-       if (domain->base.power_on)
-               domain->base.power_on(&domain->base);
-
-       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
-               pm_genpd_init(&domain->base, NULL, false);
-               ret = of_genpd_add_provider_simple(dev->of_node, &domain->base);
-               if (ret)
-                       goto genpd_err;
-       }
-
-       device_link_add(dev, dev->parent, DL_FLAG_AUTOREMOVE_CONSUMER);
-
-       return 0;
-
-genpd_err:
-       pm_genpd_remove(&domain->base);
-       imx_pgc_put_clocks(domain);
-
-       return ret;
-}
-
-static int imx_pgc_power_domain_remove(struct platform_device *pdev)
-{
-       struct imx_pm_domain *domain = pdev->dev.platform_data;
-
-       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
-               of_genpd_del_provider(pdev->dev.of_node);
-               pm_genpd_remove(&domain->base);
-               imx_pgc_put_clocks(domain);
-       }
-
-       return 0;
-}
-
-static const struct platform_device_id imx_pgc_power_domain_id[] = {
-       { "imx-pgc-power-domain"},
-       { },
-};
-
-static struct platform_driver imx_pgc_power_domain_driver = {
-       .driver = {
-               .name = "imx-pgc-pd",
-       },
-       .probe = imx_pgc_power_domain_probe,
-       .remove = imx_pgc_power_domain_remove,
-       .id_table = imx_pgc_power_domain_id,
-};
-builtin_platform_driver(imx_pgc_power_domain_driver)
-
-#define GPC_PGC_DOMAIN_ARM     0
-#define GPC_PGC_DOMAIN_PU      1
-#define GPC_PGC_DOMAIN_DISPLAY 2
-#define GPC_PGC_DOMAIN_PCI     3
-
-static struct genpd_power_state imx6_pm_domain_pu_state = {
-       .power_off_latency_ns = 25000,
-       .power_on_latency_ns = 2000000,
-};
-
-static struct imx_pm_domain imx_gpc_domains[] = {
-       [GPC_PGC_DOMAIN_ARM] = {
-               .base = {
-                       .name = "ARM",
-                       .flags = GENPD_FLAG_ALWAYS_ON,
-               },
-       },
-       [GPC_PGC_DOMAIN_PU] = {
-               .base = {
-                       .name = "PU",
-                       .power_off = imx6_pm_domain_power_off,
-                       .power_on = imx6_pm_domain_power_on,
-                       .states = &imx6_pm_domain_pu_state,
-                       .state_count = 1,
-               },
-               .reg_offs = 0x260,
-               .cntr_pdn_bit = 0,
-       },
-       [GPC_PGC_DOMAIN_DISPLAY] = {
-               .base = {
-                       .name = "DISPLAY",
-                       .power_off = imx6_pm_domain_power_off,
-                       .power_on = imx6_pm_domain_power_on,
-               },
-               .reg_offs = 0x240,
-               .cntr_pdn_bit = 4,
-       },
-       [GPC_PGC_DOMAIN_PCI] = {
-               .base = {
-                       .name = "PCI",
-                       .power_off = imx6_pm_domain_power_off,
-                       .power_on = imx6_pm_domain_power_on,
-               },
-               .reg_offs = 0x200,
-               .cntr_pdn_bit = 6,
-       },
-};
-
-struct imx_gpc_dt_data {
-       int num_domains;
-       bool err009619_present;
-       bool err006287_present;
-};
-
-static const struct imx_gpc_dt_data imx6q_dt_data = {
-       .num_domains = 2,
-       .err009619_present = false,
-       .err006287_present = false,
-};
-
-static const struct imx_gpc_dt_data imx6qp_dt_data = {
-       .num_domains = 2,
-       .err009619_present = true,
-       .err006287_present = false,
-};
-
-static const struct imx_gpc_dt_data imx6sl_dt_data = {
-       .num_domains = 3,
-       .err009619_present = false,
-       .err006287_present = true,
-};
-
-static const struct imx_gpc_dt_data imx6sx_dt_data = {
-       .num_domains = 4,
-       .err009619_present = false,
-       .err006287_present = false,
-};
-
-static const struct of_device_id imx_gpc_dt_ids[] = {
-       { .compatible = "fsl,imx6q-gpc", .data = &imx6q_dt_data },
-       { .compatible = "fsl,imx6qp-gpc", .data = &imx6qp_dt_data },
-       { .compatible = "fsl,imx6sl-gpc", .data = &imx6sl_dt_data },
-       { .compatible = "fsl,imx6sx-gpc", .data = &imx6sx_dt_data },
-       { }
-};
-
-static const struct regmap_range yes_ranges[] = {
-       regmap_reg_range(GPC_CNTR, GPC_CNTR),
-       regmap_reg_range(GPC_PGC_PCI_PDN, GPC_PGC_PCI_SR),
-       regmap_reg_range(GPC_PGC_GPU_PDN, GPC_PGC_GPU_SR),
-       regmap_reg_range(GPC_PGC_DISP_PDN, GPC_PGC_DISP_SR),
-};
-
-static const struct regmap_access_table access_table = {
-       .yes_ranges     = yes_ranges,
-       .n_yes_ranges   = ARRAY_SIZE(yes_ranges),
-};
-
-static const struct regmap_config imx_gpc_regmap_config = {
-       .reg_bits = 32,
-       .val_bits = 32,
-       .reg_stride = 4,
-       .rd_table = &access_table,
-       .wr_table = &access_table,
-       .max_register = 0x2ac,
-       .fast_io = true,
-};
-
-static struct generic_pm_domain *imx_gpc_onecell_domains[] = {
-       &imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base,
-       &imx_gpc_domains[GPC_PGC_DOMAIN_PU].base,
-};
-
-static struct genpd_onecell_data imx_gpc_onecell_data = {
-       .domains = imx_gpc_onecell_domains,
-       .num_domains = 2,
-};
-
-static int imx_gpc_old_dt_init(struct device *dev, struct regmap *regmap,
-                              unsigned int num_domains)
-{
-       struct imx_pm_domain *domain;
-       int i, ret;
-
-       for (i = 0; i < num_domains; i++) {
-               domain = &imx_gpc_domains[i];
-               domain->regmap = regmap;
-               domain->ipg_rate_mhz = 66;
-
-               if (i == 1) {
-                       domain->supply = devm_regulator_get(dev, "pu");
-                       if (IS_ERR(domain->supply))
-                               return PTR_ERR(domain->supply);
-
-                       ret = imx_pgc_get_clocks(dev, domain);
-                       if (ret)
-                               goto clk_err;
-
-                       domain->base.power_on(&domain->base);
-               }
-       }
-
-       for (i = 0; i < num_domains; i++)
-               pm_genpd_init(&imx_gpc_domains[i].base, NULL, false);
-
-       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
-               ret = of_genpd_add_provider_onecell(dev->of_node,
-                                                   &imx_gpc_onecell_data);
-               if (ret)
-                       goto genpd_err;
-       }
-
-       return 0;
-
-genpd_err:
-       for (i = 0; i < num_domains; i++)
-               pm_genpd_remove(&imx_gpc_domains[i].base);
-       imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
-clk_err:
-       return ret;
-}
-
-static int imx_gpc_probe(struct platform_device *pdev)
-{
-       const struct of_device_id *of_id =
-                       of_match_device(imx_gpc_dt_ids, &pdev->dev);
-       const struct imx_gpc_dt_data *of_id_data = of_id->data;
-       struct device_node *pgc_node;
-       struct regmap *regmap;
-       void __iomem *base;
-       int ret;
-
-       pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
-
-       /* bail out if DT too old and doesn't provide the necessary info */
-       if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
-           !pgc_node)
-               return 0;
-
-       base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base,
-                                          &imx_gpc_regmap_config);
-       if (IS_ERR(regmap)) {
-               ret = PTR_ERR(regmap);
-               dev_err(&pdev->dev, "failed to init regmap: %d\n",
-                       ret);
-               return ret;
-       }
-
-       /*
-        * Disable PU power down by runtime PM if ERR009619 is present.
-        *
-        * The PRE clock will be paused for several cycles when turning on the
-        * PU domain LDO from power down state. If PRE is in use at that time,
-        * the IPU/PRG cannot get the correct display data from the PRE.
-        *
-        * This is not a concern when the whole system enters suspend state, so
-        * it's safe to power down PU in this case.
-        */
-       if (of_id_data->err009619_present)
-               imx_gpc_domains[GPC_PGC_DOMAIN_PU].base.flags |=
-                               GENPD_FLAG_RPM_ALWAYS_ON;
-
-       /* Keep DISP always on if ERR006287 is present */
-       if (of_id_data->err006287_present)
-               imx_gpc_domains[GPC_PGC_DOMAIN_DISPLAY].base.flags |=
-                               GENPD_FLAG_ALWAYS_ON;
-
-       if (!pgc_node) {
-               ret = imx_gpc_old_dt_init(&pdev->dev, regmap,
-                                         of_id_data->num_domains);
-               if (ret)
-                       return ret;
-       } else {
-               struct imx_pm_domain *domain;
-               struct platform_device *pd_pdev;
-               struct device_node *np;
-               struct clk *ipg_clk;
-               unsigned int ipg_rate_mhz;
-               int domain_index;
-
-               ipg_clk = devm_clk_get(&pdev->dev, "ipg");
-               if (IS_ERR(ipg_clk))
-                       return PTR_ERR(ipg_clk);
-               ipg_rate_mhz = clk_get_rate(ipg_clk) / 1000000;
-
-               for_each_child_of_node(pgc_node, np) {
-                       ret = of_property_read_u32(np, "reg", &domain_index);
-                       if (ret) {
-                               of_node_put(np);
-                               return ret;
-                       }
-                       if (domain_index >= of_id_data->num_domains)
-                               continue;
-
-                       pd_pdev = platform_device_alloc("imx-pgc-power-domain",
-                                                       domain_index);
-                       if (!pd_pdev) {
-                               of_node_put(np);
-                               return -ENOMEM;
-                       }
-
-                       ret = platform_device_add_data(pd_pdev,
-                                                      &imx_gpc_domains[domain_index],
-                                                      sizeof(imx_gpc_domains[domain_index]));
-                       if (ret) {
-                               platform_device_put(pd_pdev);
-                               of_node_put(np);
-                               return ret;
-                       }
-                       domain = pd_pdev->dev.platform_data;
-                       domain->regmap = regmap;
-                       domain->ipg_rate_mhz = ipg_rate_mhz;
-
-                       pd_pdev->dev.parent = &pdev->dev;
-                       pd_pdev->dev.of_node = np;
-
-                       ret = platform_device_add(pd_pdev);
-                       if (ret) {
-                               platform_device_put(pd_pdev);
-                               of_node_put(np);
-                               return ret;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static int imx_gpc_remove(struct platform_device *pdev)
-{
-       struct device_node *pgc_node;
-       int ret;
-
-       pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
-
-       /* bail out if DT too old and doesn't provide the necessary info */
-       if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
-           !pgc_node)
-               return 0;
-
-       /*
-        * If the old DT binding is used the toplevel driver needs to
-        * de-register the power domains
-        */
-       if (!pgc_node) {
-               of_genpd_del_provider(pdev->dev.of_node);
-
-               ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_PU].base);
-               if (ret)
-                       return ret;
-               imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
-
-               ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static struct platform_driver imx_gpc_driver = {
-       .driver = {
-               .name = "imx-gpc",
-               .of_match_table = imx_gpc_dt_ids,
-       },
-       .probe = imx_gpc_probe,
-       .remove = imx_gpc_remove,
-};
-builtin_platform_driver(imx_gpc_driver)
diff --git a/drivers/genpd/imx/gpcv2.c b/drivers/genpd/imx/gpcv2.c
deleted file mode 100644 (file)
index fbd3d92..0000000
+++ /dev/null
@@ -1,1550 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright 2017 Impinj, Inc
- * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
- *
- * Based on the code of analogus driver:
- *
- * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
- */
-
-#include <linux/clk.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/pm_runtime.h>
-#include <linux/regmap.h>
-#include <linux/regulator/consumer.h>
-#include <linux/reset.h>
-#include <linux/sizes.h>
-#include <dt-bindings/power/imx7-power.h>
-#include <dt-bindings/power/imx8mq-power.h>
-#include <dt-bindings/power/imx8mm-power.h>
-#include <dt-bindings/power/imx8mn-power.h>
-#include <dt-bindings/power/imx8mp-power.h>
-
-#define GPC_LPCR_A_CORE_BSC                    0x000
-
-#define GPC_PGC_CPU_MAPPING            0x0ec
-#define IMX8MP_GPC_PGC_CPU_MAPPING     0x1cc
-
-#define IMX7_USB_HSIC_PHY_A_CORE_DOMAIN                BIT(6)
-#define IMX7_USB_OTG2_PHY_A_CORE_DOMAIN                BIT(5)
-#define IMX7_USB_OTG1_PHY_A_CORE_DOMAIN                BIT(4)
-#define IMX7_PCIE_PHY_A_CORE_DOMAIN            BIT(3)
-#define IMX7_MIPI_PHY_A_CORE_DOMAIN            BIT(2)
-
-#define IMX8M_PCIE2_A53_DOMAIN                 BIT(15)
-#define IMX8M_MIPI_CSI2_A53_DOMAIN             BIT(14)
-#define IMX8M_MIPI_CSI1_A53_DOMAIN             BIT(13)
-#define IMX8M_DISP_A53_DOMAIN                  BIT(12)
-#define IMX8M_HDMI_A53_DOMAIN                  BIT(11)
-#define IMX8M_VPU_A53_DOMAIN                   BIT(10)
-#define IMX8M_GPU_A53_DOMAIN                   BIT(9)
-#define IMX8M_DDR2_A53_DOMAIN                  BIT(8)
-#define IMX8M_DDR1_A53_DOMAIN                  BIT(7)
-#define IMX8M_OTG2_A53_DOMAIN                  BIT(5)
-#define IMX8M_OTG1_A53_DOMAIN                  BIT(4)
-#define IMX8M_PCIE1_A53_DOMAIN                 BIT(3)
-#define IMX8M_MIPI_A53_DOMAIN                  BIT(2)
-
-#define IMX8MM_VPUH1_A53_DOMAIN                        BIT(15)
-#define IMX8MM_VPUG2_A53_DOMAIN                        BIT(14)
-#define IMX8MM_VPUG1_A53_DOMAIN                        BIT(13)
-#define IMX8MM_DISPMIX_A53_DOMAIN              BIT(12)
-#define IMX8MM_VPUMIX_A53_DOMAIN               BIT(10)
-#define IMX8MM_GPUMIX_A53_DOMAIN               BIT(9)
-#define IMX8MM_GPU_A53_DOMAIN                  (BIT(8) | BIT(11))
-#define IMX8MM_DDR1_A53_DOMAIN                 BIT(7)
-#define IMX8MM_OTG2_A53_DOMAIN                 BIT(5)
-#define IMX8MM_OTG1_A53_DOMAIN                 BIT(4)
-#define IMX8MM_PCIE_A53_DOMAIN                 BIT(3)
-#define IMX8MM_MIPI_A53_DOMAIN                 BIT(2)
-
-#define IMX8MN_DISPMIX_A53_DOMAIN              BIT(12)
-#define IMX8MN_GPUMIX_A53_DOMAIN               BIT(9)
-#define IMX8MN_DDR1_A53_DOMAIN         BIT(7)
-#define IMX8MN_OTG1_A53_DOMAIN         BIT(4)
-#define IMX8MN_MIPI_A53_DOMAIN         BIT(2)
-
-#define IMX8MP_MEDIA_ISPDWP_A53_DOMAIN BIT(20)
-#define IMX8MP_HSIOMIX_A53_DOMAIN              BIT(19)
-#define IMX8MP_MIPI_PHY2_A53_DOMAIN            BIT(18)
-#define IMX8MP_HDMI_PHY_A53_DOMAIN             BIT(17)
-#define IMX8MP_HDMIMIX_A53_DOMAIN              BIT(16)
-#define IMX8MP_VPU_VC8000E_A53_DOMAIN          BIT(15)
-#define IMX8MP_VPU_G2_A53_DOMAIN               BIT(14)
-#define IMX8MP_VPU_G1_A53_DOMAIN               BIT(13)
-#define IMX8MP_MEDIAMIX_A53_DOMAIN             BIT(12)
-#define IMX8MP_GPU3D_A53_DOMAIN                        BIT(11)
-#define IMX8MP_VPUMIX_A53_DOMAIN               BIT(10)
-#define IMX8MP_GPUMIX_A53_DOMAIN               BIT(9)
-#define IMX8MP_GPU2D_A53_DOMAIN                        BIT(8)
-#define IMX8MP_AUDIOMIX_A53_DOMAIN             BIT(7)
-#define IMX8MP_MLMIX_A53_DOMAIN                        BIT(6)
-#define IMX8MP_USB2_PHY_A53_DOMAIN             BIT(5)
-#define IMX8MP_USB1_PHY_A53_DOMAIN             BIT(4)
-#define IMX8MP_PCIE_PHY_A53_DOMAIN             BIT(3)
-#define IMX8MP_MIPI_PHY1_A53_DOMAIN            BIT(2)
-
-#define IMX8MP_GPC_PU_PGC_SW_PUP_REQ   0x0d8
-#define IMX8MP_GPC_PU_PGC_SW_PDN_REQ   0x0e4
-
-#define GPC_PU_PGC_SW_PUP_REQ          0x0f8
-#define GPC_PU_PGC_SW_PDN_REQ          0x104
-
-#define IMX7_USB_HSIC_PHY_SW_Pxx_REQ           BIT(4)
-#define IMX7_USB_OTG2_PHY_SW_Pxx_REQ           BIT(3)
-#define IMX7_USB_OTG1_PHY_SW_Pxx_REQ           BIT(2)
-#define IMX7_PCIE_PHY_SW_Pxx_REQ               BIT(1)
-#define IMX7_MIPI_PHY_SW_Pxx_REQ               BIT(0)
-
-#define IMX8M_PCIE2_SW_Pxx_REQ                 BIT(13)
-#define IMX8M_MIPI_CSI2_SW_Pxx_REQ             BIT(12)
-#define IMX8M_MIPI_CSI1_SW_Pxx_REQ             BIT(11)
-#define IMX8M_DISP_SW_Pxx_REQ                  BIT(10)
-#define IMX8M_HDMI_SW_Pxx_REQ                  BIT(9)
-#define IMX8M_VPU_SW_Pxx_REQ                   BIT(8)
-#define IMX8M_GPU_SW_Pxx_REQ                   BIT(7)
-#define IMX8M_DDR2_SW_Pxx_REQ                  BIT(6)
-#define IMX8M_DDR1_SW_Pxx_REQ                  BIT(5)
-#define IMX8M_OTG2_SW_Pxx_REQ                  BIT(3)
-#define IMX8M_OTG1_SW_Pxx_REQ                  BIT(2)
-#define IMX8M_PCIE1_SW_Pxx_REQ                 BIT(1)
-#define IMX8M_MIPI_SW_Pxx_REQ                  BIT(0)
-
-#define IMX8MM_VPUH1_SW_Pxx_REQ                        BIT(13)
-#define IMX8MM_VPUG2_SW_Pxx_REQ                        BIT(12)
-#define IMX8MM_VPUG1_SW_Pxx_REQ                        BIT(11)
-#define IMX8MM_DISPMIX_SW_Pxx_REQ              BIT(10)
-#define IMX8MM_VPUMIX_SW_Pxx_REQ               BIT(8)
-#define IMX8MM_GPUMIX_SW_Pxx_REQ               BIT(7)
-#define IMX8MM_GPU_SW_Pxx_REQ                  (BIT(6) | BIT(9))
-#define IMX8MM_DDR1_SW_Pxx_REQ                 BIT(5)
-#define IMX8MM_OTG2_SW_Pxx_REQ                 BIT(3)
-#define IMX8MM_OTG1_SW_Pxx_REQ                 BIT(2)
-#define IMX8MM_PCIE_SW_Pxx_REQ                 BIT(1)
-#define IMX8MM_MIPI_SW_Pxx_REQ                 BIT(0)
-
-#define IMX8MN_DISPMIX_SW_Pxx_REQ              BIT(10)
-#define IMX8MN_GPUMIX_SW_Pxx_REQ               BIT(7)
-#define IMX8MN_DDR1_SW_Pxx_REQ         BIT(5)
-#define IMX8MN_OTG1_SW_Pxx_REQ         BIT(2)
-#define IMX8MN_MIPI_SW_Pxx_REQ         BIT(0)
-
-#define IMX8MP_DDRMIX_Pxx_REQ                  BIT(19)
-#define IMX8MP_MEDIA_ISP_DWP_Pxx_REQ           BIT(18)
-#define IMX8MP_HSIOMIX_Pxx_REQ                 BIT(17)
-#define IMX8MP_MIPI_PHY2_Pxx_REQ               BIT(16)
-#define IMX8MP_HDMI_PHY_Pxx_REQ                        BIT(15)
-#define IMX8MP_HDMIMIX_Pxx_REQ                 BIT(14)
-#define IMX8MP_VPU_VC8K_Pxx_REQ                        BIT(13)
-#define IMX8MP_VPU_G2_Pxx_REQ                  BIT(12)
-#define IMX8MP_VPU_G1_Pxx_REQ                  BIT(11)
-#define IMX8MP_MEDIMIX_Pxx_REQ                 BIT(10)
-#define IMX8MP_GPU_3D_Pxx_REQ                  BIT(9)
-#define IMX8MP_VPU_MIX_SHARE_LOGIC_Pxx_REQ     BIT(8)
-#define IMX8MP_GPU_SHARE_LOGIC_Pxx_REQ         BIT(7)
-#define IMX8MP_GPU_2D_Pxx_REQ                  BIT(6)
-#define IMX8MP_AUDIOMIX_Pxx_REQ                        BIT(5)
-#define IMX8MP_MLMIX_Pxx_REQ                   BIT(4)
-#define IMX8MP_USB2_PHY_Pxx_REQ                        BIT(3)
-#define IMX8MP_USB1_PHY_Pxx_REQ                        BIT(2)
-#define IMX8MP_PCIE_PHY_SW_Pxx_REQ             BIT(1)
-#define IMX8MP_MIPI_PHY1_SW_Pxx_REQ            BIT(0)
-
-#define GPC_M4_PU_PDN_FLG              0x1bc
-
-#define IMX8MP_GPC_PU_PWRHSK           0x190
-#define GPC_PU_PWRHSK                  0x1fc
-
-#define IMX8M_GPU_HSK_PWRDNACKN                        BIT(26)
-#define IMX8M_VPU_HSK_PWRDNACKN                        BIT(25)
-#define IMX8M_DISP_HSK_PWRDNACKN               BIT(24)
-#define IMX8M_GPU_HSK_PWRDNREQN                        BIT(6)
-#define IMX8M_VPU_HSK_PWRDNREQN                        BIT(5)
-#define IMX8M_DISP_HSK_PWRDNREQN               BIT(4)
-
-#define IMX8MM_GPUMIX_HSK_PWRDNACKN            BIT(29)
-#define IMX8MM_GPU_HSK_PWRDNACKN               (BIT(27) | BIT(28))
-#define IMX8MM_VPUMIX_HSK_PWRDNACKN            BIT(26)
-#define IMX8MM_DISPMIX_HSK_PWRDNACKN           BIT(25)
-#define IMX8MM_HSIO_HSK_PWRDNACKN              (BIT(23) | BIT(24))
-#define IMX8MM_GPUMIX_HSK_PWRDNREQN            BIT(11)
-#define IMX8MM_GPU_HSK_PWRDNREQN               (BIT(9) | BIT(10))
-#define IMX8MM_VPUMIX_HSK_PWRDNREQN            BIT(8)
-#define IMX8MM_DISPMIX_HSK_PWRDNREQN           BIT(7)
-#define IMX8MM_HSIO_HSK_PWRDNREQN              (BIT(5) | BIT(6))
-
-#define IMX8MN_GPUMIX_HSK_PWRDNACKN            (BIT(29) | BIT(27))
-#define IMX8MN_DISPMIX_HSK_PWRDNACKN           BIT(25)
-#define IMX8MN_HSIO_HSK_PWRDNACKN              BIT(23)
-#define IMX8MN_GPUMIX_HSK_PWRDNREQN            (BIT(11) | BIT(9))
-#define IMX8MN_DISPMIX_HSK_PWRDNREQN           BIT(7)
-#define IMX8MN_HSIO_HSK_PWRDNREQN              BIT(5)
-
-#define IMX8MP_MEDIAMIX_PWRDNACKN              BIT(30)
-#define IMX8MP_HDMIMIX_PWRDNACKN               BIT(29)
-#define IMX8MP_HSIOMIX_PWRDNACKN               BIT(28)
-#define IMX8MP_VPUMIX_PWRDNACKN                        BIT(26)
-#define IMX8MP_GPUMIX_PWRDNACKN                        BIT(25)
-#define IMX8MP_MLMIX_PWRDNACKN                 (BIT(23) | BIT(24))
-#define IMX8MP_AUDIOMIX_PWRDNACKN              (BIT(20) | BIT(31))
-#define IMX8MP_MEDIAMIX_PWRDNREQN              BIT(14)
-#define IMX8MP_HDMIMIX_PWRDNREQN               BIT(13)
-#define IMX8MP_HSIOMIX_PWRDNREQN               BIT(12)
-#define IMX8MP_VPUMIX_PWRDNREQN                        BIT(10)
-#define IMX8MP_GPUMIX_PWRDNREQN                        BIT(9)
-#define IMX8MP_MLMIX_PWRDNREQN                 (BIT(7) | BIT(8))
-#define IMX8MP_AUDIOMIX_PWRDNREQN              (BIT(4) | BIT(15))
-
-/*
- * The PGC offset values in Reference Manual
- * (Rev. 1, 01/2018 and the older ones) GPC chapter's
- * GPC_PGC memory map are incorrect, below offset
- * values are from design RTL.
- */
-#define IMX7_PGC_MIPI                  16
-#define IMX7_PGC_PCIE                  17
-#define IMX7_PGC_USB_HSIC              20
-
-#define IMX8M_PGC_MIPI                 16
-#define IMX8M_PGC_PCIE1                        17
-#define IMX8M_PGC_OTG1                 18
-#define IMX8M_PGC_OTG2                 19
-#define IMX8M_PGC_DDR1                 21
-#define IMX8M_PGC_GPU                  23
-#define IMX8M_PGC_VPU                  24
-#define IMX8M_PGC_DISP                 26
-#define IMX8M_PGC_MIPI_CSI1            27
-#define IMX8M_PGC_MIPI_CSI2            28
-#define IMX8M_PGC_PCIE2                        29
-
-#define IMX8MM_PGC_MIPI                        16
-#define IMX8MM_PGC_PCIE                        17
-#define IMX8MM_PGC_OTG1                        18
-#define IMX8MM_PGC_OTG2                        19
-#define IMX8MM_PGC_DDR1                        21
-#define IMX8MM_PGC_GPU2D               22
-#define IMX8MM_PGC_GPUMIX              23
-#define IMX8MM_PGC_VPUMIX              24
-#define IMX8MM_PGC_GPU3D               25
-#define IMX8MM_PGC_DISPMIX             26
-#define IMX8MM_PGC_VPUG1               27
-#define IMX8MM_PGC_VPUG2               28
-#define IMX8MM_PGC_VPUH1               29
-
-#define IMX8MN_PGC_MIPI                16
-#define IMX8MN_PGC_OTG1                18
-#define IMX8MN_PGC_DDR1                21
-#define IMX8MN_PGC_GPUMIX              23
-#define IMX8MN_PGC_DISPMIX             26
-
-#define IMX8MP_PGC_NOC                 9
-#define IMX8MP_PGC_MIPI1               12
-#define IMX8MP_PGC_PCIE                        13
-#define IMX8MP_PGC_USB1                        14
-#define IMX8MP_PGC_USB2                        15
-#define IMX8MP_PGC_MLMIX               16
-#define IMX8MP_PGC_AUDIOMIX            17
-#define IMX8MP_PGC_GPU2D               18
-#define IMX8MP_PGC_GPUMIX              19
-#define IMX8MP_PGC_VPUMIX              20
-#define IMX8MP_PGC_GPU3D               21
-#define IMX8MP_PGC_MEDIAMIX            22
-#define IMX8MP_PGC_VPU_G1              23
-#define IMX8MP_PGC_VPU_G2              24
-#define IMX8MP_PGC_VPU_VC8000E         25
-#define IMX8MP_PGC_HDMIMIX             26
-#define IMX8MP_PGC_HDMI                        27
-#define IMX8MP_PGC_MIPI2               28
-#define IMX8MP_PGC_HSIOMIX             29
-#define IMX8MP_PGC_MEDIA_ISP_DWP       30
-#define IMX8MP_PGC_DDRMIX              31
-
-#define GPC_PGC_CTRL(n)                        (0x800 + (n) * 0x40)
-#define GPC_PGC_SR(n)                  (GPC_PGC_CTRL(n) + 0xc)
-
-#define GPC_PGC_CTRL_PCR               BIT(0)
-
-struct imx_pgc_regs {
-       u16 map;
-       u16 pup;
-       u16 pdn;
-       u16 hsk;
-};
-
-struct imx_pgc_domain {
-       struct generic_pm_domain genpd;
-       struct regmap *regmap;
-       const struct imx_pgc_regs *regs;
-       struct regulator *regulator;
-       struct reset_control *reset;
-       struct clk_bulk_data *clks;
-       int num_clks;
-
-       unsigned long pgc;
-
-       const struct {
-               u32 pxx;
-               u32 map;
-               u32 hskreq;
-               u32 hskack;
-       } bits;
-
-       const int voltage;
-       const bool keep_clocks;
-       struct device *dev;
-
-       unsigned int pgc_sw_pup_reg;
-       unsigned int pgc_sw_pdn_reg;
-};
-
-struct imx_pgc_domain_data {
-       const struct imx_pgc_domain *domains;
-       size_t domains_num;
-       const struct regmap_access_table *reg_access_table;
-       const struct imx_pgc_regs *pgc_regs;
-};
-
-static inline struct imx_pgc_domain *
-to_imx_pgc_domain(struct generic_pm_domain *genpd)
-{
-       return container_of(genpd, struct imx_pgc_domain, genpd);
-}
-
-static int imx_pgc_power_up(struct generic_pm_domain *genpd)
-{
-       struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd);
-       u32 reg_val, pgc;
-       int ret;
-
-       ret = pm_runtime_get_sync(domain->dev);
-       if (ret < 0) {
-               pm_runtime_put_noidle(domain->dev);
-               return ret;
-       }
-
-       if (!IS_ERR(domain->regulator)) {
-               ret = regulator_enable(domain->regulator);
-               if (ret) {
-                       dev_err(domain->dev,
-                               "failed to enable regulator: %pe\n",
-                               ERR_PTR(ret));
-                       goto out_put_pm;
-               }
-       }
-
-       reset_control_assert(domain->reset);
-
-       /* Enable reset clocks for all devices in the domain */
-       ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
-       if (ret) {
-               dev_err(domain->dev, "failed to enable reset clocks\n");
-               goto out_regulator_disable;
-       }
-
-       /* delays for reset to propagate */
-       udelay(5);
-
-       if (domain->bits.pxx) {
-               /* request the domain to power up */
-               regmap_update_bits(domain->regmap, domain->regs->pup,
-                                  domain->bits.pxx, domain->bits.pxx);
-               /*
-                * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
-                * for PUP_REQ/PDN_REQ bit to be cleared
-                */
-               ret = regmap_read_poll_timeout(domain->regmap,
-                                              domain->regs->pup, reg_val,
-                                              !(reg_val & domain->bits.pxx),
-                                              0, USEC_PER_MSEC);
-               if (ret) {
-                       dev_err(domain->dev, "failed to command PGC\n");
-                       goto out_clk_disable;
-               }
-
-               /* disable power control */
-               for_each_set_bit(pgc, &domain->pgc, 32) {
-                       regmap_clear_bits(domain->regmap, GPC_PGC_CTRL(pgc),
-                                         GPC_PGC_CTRL_PCR);
-               }
-       }
-
-       /* delay for reset to propagate */
-       udelay(5);
-
-       reset_control_deassert(domain->reset);
-
-       /* request the ADB400 to power up */
-       if (domain->bits.hskreq) {
-               regmap_update_bits(domain->regmap, domain->regs->hsk,
-                                  domain->bits.hskreq, domain->bits.hskreq);
-
-               /*
-                * ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk, reg_val,
-                *                                (reg_val & domain->bits.hskack), 0,
-                *                                USEC_PER_MSEC);
-                * Technically we need the commented code to wait handshake. But that needs
-                * the BLK-CTL module BUS clk-en bit being set.
-                *
-                * There is a separate BLK-CTL module and we will have such a driver for it,
-                * that driver will set the BUS clk-en bit and handshake will be triggered
-                * automatically there. Just add a delay and suppose the handshake finish
-                * after that.
-                */
-       }
-
-       /* Disable reset clocks for all devices in the domain */
-       if (!domain->keep_clocks)
-               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
-
-       return 0;
-
-out_clk_disable:
-       clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
-out_regulator_disable:
-       if (!IS_ERR(domain->regulator))
-               regulator_disable(domain->regulator);
-out_put_pm:
-       pm_runtime_put(domain->dev);
-
-       return ret;
-}
-
-static int imx_pgc_power_down(struct generic_pm_domain *genpd)
-{
-       struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd);
-       u32 reg_val, pgc;
-       int ret;
-
-       /* Enable reset clocks for all devices in the domain */
-       if (!domain->keep_clocks) {
-               ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
-               if (ret) {
-                       dev_err(domain->dev, "failed to enable reset clocks\n");
-                       return ret;
-               }
-       }
-
-       /* request the ADB400 to power down */
-       if (domain->bits.hskreq) {
-               regmap_clear_bits(domain->regmap, domain->regs->hsk,
-                                 domain->bits.hskreq);
-
-               ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk,
-                                              reg_val,
-                                              !(reg_val & domain->bits.hskack),
-                                              0, USEC_PER_MSEC);
-               if (ret) {
-                       dev_err(domain->dev, "failed to power down ADB400\n");
-                       goto out_clk_disable;
-               }
-       }
-
-       if (domain->bits.pxx) {
-               /* enable power control */
-               for_each_set_bit(pgc, &domain->pgc, 32) {
-                       regmap_update_bits(domain->regmap, GPC_PGC_CTRL(pgc),
-                                          GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
-               }
-
-               /* request the domain to power down */
-               regmap_update_bits(domain->regmap, domain->regs->pdn,
-                                  domain->bits.pxx, domain->bits.pxx);
-               /*
-                * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
-                * for PUP_REQ/PDN_REQ bit to be cleared
-                */
-               ret = regmap_read_poll_timeout(domain->regmap,
-                                              domain->regs->pdn, reg_val,
-                                              !(reg_val & domain->bits.pxx),
-                                              0, USEC_PER_MSEC);
-               if (ret) {
-                       dev_err(domain->dev, "failed to command PGC\n");
-                       goto out_clk_disable;
-               }
-       }
-
-       /* Disable reset clocks for all devices in the domain */
-       clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
-
-       if (!IS_ERR(domain->regulator)) {
-               ret = regulator_disable(domain->regulator);
-               if (ret) {
-                       dev_err(domain->dev,
-                               "failed to disable regulator: %pe\n",
-                               ERR_PTR(ret));
-                       return ret;
-               }
-       }
-
-       pm_runtime_put_sync_suspend(domain->dev);
-
-       return 0;
-
-out_clk_disable:
-       if (!domain->keep_clocks)
-               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
-
-       return ret;
-}
-
-static const struct imx_pgc_domain imx7_pgc_domains[] = {
-       [IMX7_POWER_DOMAIN_MIPI_PHY] = {
-               .genpd = {
-                       .name      = "mipi-phy",
-               },
-               .bits  = {
-                       .pxx = IMX7_MIPI_PHY_SW_Pxx_REQ,
-                       .map = IMX7_MIPI_PHY_A_CORE_DOMAIN,
-               },
-               .voltage   = 1000000,
-               .pgc       = BIT(IMX7_PGC_MIPI),
-       },
-
-       [IMX7_POWER_DOMAIN_PCIE_PHY] = {
-               .genpd = {
-                       .name      = "pcie-phy",
-               },
-               .bits  = {
-                       .pxx = IMX7_PCIE_PHY_SW_Pxx_REQ,
-                       .map = IMX7_PCIE_PHY_A_CORE_DOMAIN,
-               },
-               .voltage   = 1000000,
-               .pgc       = BIT(IMX7_PGC_PCIE),
-       },
-
-       [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = {
-               .genpd = {
-                       .name      = "usb-hsic-phy",
-               },
-               .bits  = {
-                       .pxx = IMX7_USB_HSIC_PHY_SW_Pxx_REQ,
-                       .map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN,
-               },
-               .voltage   = 1200000,
-               .pgc       = BIT(IMX7_PGC_USB_HSIC),
-       },
-};
-
-static const struct regmap_range imx7_yes_ranges[] = {
-               regmap_reg_range(GPC_LPCR_A_CORE_BSC,
-                                GPC_M4_PU_PDN_FLG),
-               regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_MIPI),
-                                GPC_PGC_SR(IMX7_PGC_MIPI)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_PCIE),
-                                GPC_PGC_SR(IMX7_PGC_PCIE)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_USB_HSIC),
-                                GPC_PGC_SR(IMX7_PGC_USB_HSIC)),
-};
-
-static const struct regmap_access_table imx7_access_table = {
-       .yes_ranges     = imx7_yes_ranges,
-       .n_yes_ranges   = ARRAY_SIZE(imx7_yes_ranges),
-};
-
-static const struct imx_pgc_regs imx7_pgc_regs = {
-       .map = GPC_PGC_CPU_MAPPING,
-       .pup = GPC_PU_PGC_SW_PUP_REQ,
-       .pdn = GPC_PU_PGC_SW_PDN_REQ,
-       .hsk = GPC_PU_PWRHSK,
-};
-
-static const struct imx_pgc_domain_data imx7_pgc_domain_data = {
-       .domains = imx7_pgc_domains,
-       .domains_num = ARRAY_SIZE(imx7_pgc_domains),
-       .reg_access_table = &imx7_access_table,
-       .pgc_regs = &imx7_pgc_regs,
-};
-
-static const struct imx_pgc_domain imx8m_pgc_domains[] = {
-       [IMX8M_POWER_DOMAIN_MIPI] = {
-               .genpd = {
-                       .name      = "mipi",
-               },
-               .bits  = {
-                       .pxx = IMX8M_MIPI_SW_Pxx_REQ,
-                       .map = IMX8M_MIPI_A53_DOMAIN,
-               },
-               .pgc       = BIT(IMX8M_PGC_MIPI),
-       },
-
-       [IMX8M_POWER_DOMAIN_PCIE1] = {
-               .genpd = {
-                       .name = "pcie1",
-               },
-               .bits  = {
-                       .pxx = IMX8M_PCIE1_SW_Pxx_REQ,
-                       .map = IMX8M_PCIE1_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8M_PGC_PCIE1),
-       },
-
-       [IMX8M_POWER_DOMAIN_USB_OTG1] = {
-               .genpd = {
-                       .name = "usb-otg1",
-               },
-               .bits  = {
-                       .pxx = IMX8M_OTG1_SW_Pxx_REQ,
-                       .map = IMX8M_OTG1_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8M_PGC_OTG1),
-       },
-
-       [IMX8M_POWER_DOMAIN_USB_OTG2] = {
-               .genpd = {
-                       .name = "usb-otg2",
-               },
-               .bits  = {
-                       .pxx = IMX8M_OTG2_SW_Pxx_REQ,
-                       .map = IMX8M_OTG2_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8M_PGC_OTG2),
-       },
-
-       [IMX8M_POWER_DOMAIN_DDR1] = {
-               .genpd = {
-                       .name = "ddr1",
-               },
-               .bits  = {
-                       .pxx = IMX8M_DDR1_SW_Pxx_REQ,
-                       .map = IMX8M_DDR2_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8M_PGC_DDR1),
-       },
-
-       [IMX8M_POWER_DOMAIN_GPU] = {
-               .genpd = {
-                       .name = "gpu",
-               },
-               .bits  = {
-                       .pxx = IMX8M_GPU_SW_Pxx_REQ,
-                       .map = IMX8M_GPU_A53_DOMAIN,
-                       .hskreq = IMX8M_GPU_HSK_PWRDNREQN,
-                       .hskack = IMX8M_GPU_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8M_PGC_GPU),
-       },
-
-       [IMX8M_POWER_DOMAIN_VPU] = {
-               .genpd = {
-                       .name = "vpu",
-               },
-               .bits  = {
-                       .pxx = IMX8M_VPU_SW_Pxx_REQ,
-                       .map = IMX8M_VPU_A53_DOMAIN,
-                       .hskreq = IMX8M_VPU_HSK_PWRDNREQN,
-                       .hskack = IMX8M_VPU_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8M_PGC_VPU),
-               .keep_clocks = true,
-       },
-
-       [IMX8M_POWER_DOMAIN_DISP] = {
-               .genpd = {
-                       .name = "disp",
-               },
-               .bits  = {
-                       .pxx = IMX8M_DISP_SW_Pxx_REQ,
-                       .map = IMX8M_DISP_A53_DOMAIN,
-                       .hskreq = IMX8M_DISP_HSK_PWRDNREQN,
-                       .hskack = IMX8M_DISP_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8M_PGC_DISP),
-       },
-
-       [IMX8M_POWER_DOMAIN_MIPI_CSI1] = {
-               .genpd = {
-                       .name = "mipi-csi1",
-               },
-               .bits  = {
-                       .pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ,
-                       .map = IMX8M_MIPI_CSI1_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8M_PGC_MIPI_CSI1),
-       },
-
-       [IMX8M_POWER_DOMAIN_MIPI_CSI2] = {
-               .genpd = {
-                       .name = "mipi-csi2",
-               },
-               .bits  = {
-                       .pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ,
-                       .map = IMX8M_MIPI_CSI2_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8M_PGC_MIPI_CSI2),
-       },
-
-       [IMX8M_POWER_DOMAIN_PCIE2] = {
-               .genpd = {
-                       .name = "pcie2",
-               },
-               .bits  = {
-                       .pxx = IMX8M_PCIE2_SW_Pxx_REQ,
-                       .map = IMX8M_PCIE2_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8M_PGC_PCIE2),
-       },
-};
-
-static const struct regmap_range imx8m_yes_ranges[] = {
-               regmap_reg_range(GPC_LPCR_A_CORE_BSC,
-                                GPC_PU_PWRHSK),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI),
-                                GPC_PGC_SR(IMX8M_PGC_MIPI)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE1),
-                                GPC_PGC_SR(IMX8M_PGC_PCIE1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG1),
-                                GPC_PGC_SR(IMX8M_PGC_OTG1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG2),
-                                GPC_PGC_SR(IMX8M_PGC_OTG2)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DDR1),
-                                GPC_PGC_SR(IMX8M_PGC_DDR1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_GPU),
-                                GPC_PGC_SR(IMX8M_PGC_GPU)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_VPU),
-                                GPC_PGC_SR(IMX8M_PGC_VPU)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DISP),
-                                GPC_PGC_SR(IMX8M_PGC_DISP)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI1),
-                                GPC_PGC_SR(IMX8M_PGC_MIPI_CSI1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI2),
-                                GPC_PGC_SR(IMX8M_PGC_MIPI_CSI2)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE2),
-                                GPC_PGC_SR(IMX8M_PGC_PCIE2)),
-};
-
-static const struct regmap_access_table imx8m_access_table = {
-       .yes_ranges     = imx8m_yes_ranges,
-       .n_yes_ranges   = ARRAY_SIZE(imx8m_yes_ranges),
-};
-
-static const struct imx_pgc_domain_data imx8m_pgc_domain_data = {
-       .domains = imx8m_pgc_domains,
-       .domains_num = ARRAY_SIZE(imx8m_pgc_domains),
-       .reg_access_table = &imx8m_access_table,
-       .pgc_regs = &imx7_pgc_regs,
-};
-
-static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
-       [IMX8MM_POWER_DOMAIN_HSIOMIX] = {
-               .genpd = {
-                       .name = "hsiomix",
-               },
-               .bits  = {
-                       .pxx = 0, /* no power sequence control */
-                       .map = 0, /* no power sequence control */
-                       .hskreq = IMX8MM_HSIO_HSK_PWRDNREQN,
-                       .hskack = IMX8MM_HSIO_HSK_PWRDNACKN,
-               },
-               .keep_clocks = true,
-       },
-
-       [IMX8MM_POWER_DOMAIN_PCIE] = {
-               .genpd = {
-                       .name = "pcie",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_PCIE_SW_Pxx_REQ,
-                       .map = IMX8MM_PCIE_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_PCIE),
-       },
-
-       [IMX8MM_POWER_DOMAIN_OTG1] = {
-               .genpd = {
-                       .name = "usb-otg1",
-                       .flags = GENPD_FLAG_ACTIVE_WAKEUP,
-               },
-               .bits  = {
-                       .pxx = IMX8MM_OTG1_SW_Pxx_REQ,
-                       .map = IMX8MM_OTG1_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_OTG1),
-       },
-
-       [IMX8MM_POWER_DOMAIN_OTG2] = {
-               .genpd = {
-                       .name = "usb-otg2",
-                       .flags = GENPD_FLAG_ACTIVE_WAKEUP,
-               },
-               .bits  = {
-                       .pxx = IMX8MM_OTG2_SW_Pxx_REQ,
-                       .map = IMX8MM_OTG2_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_OTG2),
-       },
-
-       [IMX8MM_POWER_DOMAIN_GPUMIX] = {
-               .genpd = {
-                       .name = "gpumix",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_GPUMIX_SW_Pxx_REQ,
-                       .map = IMX8MM_GPUMIX_A53_DOMAIN,
-                       .hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN,
-                       .hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_GPUMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MM_POWER_DOMAIN_GPU] = {
-               .genpd = {
-                       .name = "gpu",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_GPU_SW_Pxx_REQ,
-                       .map = IMX8MM_GPU_A53_DOMAIN,
-                       .hskreq = IMX8MM_GPU_HSK_PWRDNREQN,
-                       .hskack = IMX8MM_GPU_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_GPU2D) | BIT(IMX8MM_PGC_GPU3D),
-       },
-
-       [IMX8MM_POWER_DOMAIN_VPUMIX] = {
-               .genpd = {
-                       .name = "vpumix",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_VPUMIX_SW_Pxx_REQ,
-                       .map = IMX8MM_VPUMIX_A53_DOMAIN,
-                       .hskreq = IMX8MM_VPUMIX_HSK_PWRDNREQN,
-                       .hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_VPUMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MM_POWER_DOMAIN_VPUG1] = {
-               .genpd = {
-                       .name = "vpu-g1",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_VPUG1_SW_Pxx_REQ,
-                       .map = IMX8MM_VPUG1_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_VPUG1),
-       },
-
-       [IMX8MM_POWER_DOMAIN_VPUG2] = {
-               .genpd = {
-                       .name = "vpu-g2",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_VPUG2_SW_Pxx_REQ,
-                       .map = IMX8MM_VPUG2_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_VPUG2),
-       },
-
-       [IMX8MM_POWER_DOMAIN_VPUH1] = {
-               .genpd = {
-                       .name = "vpu-h1",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_VPUH1_SW_Pxx_REQ,
-                       .map = IMX8MM_VPUH1_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_VPUH1),
-               .keep_clocks = true,
-       },
-
-       [IMX8MM_POWER_DOMAIN_DISPMIX] = {
-               .genpd = {
-                       .name = "dispmix",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_DISPMIX_SW_Pxx_REQ,
-                       .map = IMX8MM_DISPMIX_A53_DOMAIN,
-                       .hskreq = IMX8MM_DISPMIX_HSK_PWRDNREQN,
-                       .hskack = IMX8MM_DISPMIX_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_DISPMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MM_POWER_DOMAIN_MIPI] = {
-               .genpd = {
-                       .name = "mipi",
-               },
-               .bits  = {
-                       .pxx = IMX8MM_MIPI_SW_Pxx_REQ,
-                       .map = IMX8MM_MIPI_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MM_PGC_MIPI),
-       },
-};
-
-static const struct regmap_range imx8mm_yes_ranges[] = {
-               regmap_reg_range(GPC_LPCR_A_CORE_BSC,
-                                GPC_PU_PWRHSK),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_MIPI),
-                                GPC_PGC_SR(IMX8MM_PGC_MIPI)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_PCIE),
-                                GPC_PGC_SR(IMX8MM_PGC_PCIE)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_OTG1),
-                                GPC_PGC_SR(IMX8MM_PGC_OTG1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_OTG2),
-                                GPC_PGC_SR(IMX8MM_PGC_OTG2)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_DDR1),
-                                GPC_PGC_SR(IMX8MM_PGC_DDR1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPU2D),
-                                GPC_PGC_SR(IMX8MM_PGC_GPU2D)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPUMIX),
-                                GPC_PGC_SR(IMX8MM_PGC_GPUMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUMIX),
-                                GPC_PGC_SR(IMX8MM_PGC_VPUMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPU3D),
-                                GPC_PGC_SR(IMX8MM_PGC_GPU3D)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_DISPMIX),
-                                GPC_PGC_SR(IMX8MM_PGC_DISPMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUG1),
-                                GPC_PGC_SR(IMX8MM_PGC_VPUG1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUG2),
-                                GPC_PGC_SR(IMX8MM_PGC_VPUG2)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUH1),
-                                GPC_PGC_SR(IMX8MM_PGC_VPUH1)),
-};
-
-static const struct regmap_access_table imx8mm_access_table = {
-       .yes_ranges     = imx8mm_yes_ranges,
-       .n_yes_ranges   = ARRAY_SIZE(imx8mm_yes_ranges),
-};
-
-static const struct imx_pgc_domain_data imx8mm_pgc_domain_data = {
-       .domains = imx8mm_pgc_domains,
-       .domains_num = ARRAY_SIZE(imx8mm_pgc_domains),
-       .reg_access_table = &imx8mm_access_table,
-       .pgc_regs = &imx7_pgc_regs,
-};
-
-static const struct imx_pgc_domain imx8mp_pgc_domains[] = {
-       [IMX8MP_POWER_DOMAIN_MIPI_PHY1] = {
-               .genpd = {
-                       .name = "mipi-phy1",
-               },
-               .bits = {
-                       .pxx = IMX8MP_MIPI_PHY1_SW_Pxx_REQ,
-                       .map = IMX8MP_MIPI_PHY1_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_MIPI1),
-       },
-
-       [IMX8MP_POWER_DOMAIN_PCIE_PHY] = {
-               .genpd = {
-                       .name = "pcie-phy1",
-               },
-               .bits = {
-                       .pxx = IMX8MP_PCIE_PHY_SW_Pxx_REQ,
-                       .map = IMX8MP_PCIE_PHY_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_PCIE),
-       },
-
-       [IMX8MP_POWER_DOMAIN_USB1_PHY] = {
-               .genpd = {
-                       .name = "usb-otg1",
-               },
-               .bits = {
-                       .pxx = IMX8MP_USB1_PHY_Pxx_REQ,
-                       .map = IMX8MP_USB1_PHY_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_USB1),
-       },
-
-       [IMX8MP_POWER_DOMAIN_USB2_PHY] = {
-               .genpd = {
-                       .name = "usb-otg2",
-               },
-               .bits = {
-                       .pxx = IMX8MP_USB2_PHY_Pxx_REQ,
-                       .map = IMX8MP_USB2_PHY_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_USB2),
-       },
-
-       [IMX8MP_POWER_DOMAIN_MLMIX] = {
-               .genpd = {
-                       .name = "mlmix",
-               },
-               .bits = {
-                       .pxx = IMX8MP_MLMIX_Pxx_REQ,
-                       .map = IMX8MP_MLMIX_A53_DOMAIN,
-                       .hskreq = IMX8MP_MLMIX_PWRDNREQN,
-                       .hskack = IMX8MP_MLMIX_PWRDNACKN,
-               },
-               .pgc = BIT(IMX8MP_PGC_MLMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MP_POWER_DOMAIN_AUDIOMIX] = {
-               .genpd = {
-                       .name = "audiomix",
-               },
-               .bits = {
-                       .pxx = IMX8MP_AUDIOMIX_Pxx_REQ,
-                       .map = IMX8MP_AUDIOMIX_A53_DOMAIN,
-                       .hskreq = IMX8MP_AUDIOMIX_PWRDNREQN,
-                       .hskack = IMX8MP_AUDIOMIX_PWRDNACKN,
-               },
-               .pgc = BIT(IMX8MP_PGC_AUDIOMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MP_POWER_DOMAIN_GPU2D] = {
-               .genpd = {
-                       .name = "gpu2d",
-               },
-               .bits = {
-                       .pxx = IMX8MP_GPU_2D_Pxx_REQ,
-                       .map = IMX8MP_GPU2D_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_GPU2D),
-       },
-
-       [IMX8MP_POWER_DOMAIN_GPUMIX] = {
-               .genpd = {
-                       .name = "gpumix",
-               },
-               .bits = {
-                       .pxx = IMX8MP_GPU_SHARE_LOGIC_Pxx_REQ,
-                       .map = IMX8MP_GPUMIX_A53_DOMAIN,
-                       .hskreq = IMX8MP_GPUMIX_PWRDNREQN,
-                       .hskack = IMX8MP_GPUMIX_PWRDNACKN,
-               },
-               .pgc = BIT(IMX8MP_PGC_GPUMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MP_POWER_DOMAIN_VPUMIX] = {
-               .genpd = {
-                       .name = "vpumix",
-               },
-               .bits = {
-                       .pxx = IMX8MP_VPU_MIX_SHARE_LOGIC_Pxx_REQ,
-                       .map = IMX8MP_VPUMIX_A53_DOMAIN,
-                       .hskreq = IMX8MP_VPUMIX_PWRDNREQN,
-                       .hskack = IMX8MP_VPUMIX_PWRDNACKN,
-               },
-               .pgc = BIT(IMX8MP_PGC_VPUMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MP_POWER_DOMAIN_GPU3D] = {
-               .genpd = {
-                       .name = "gpu3d",
-               },
-               .bits = {
-                       .pxx = IMX8MP_GPU_3D_Pxx_REQ,
-                       .map = IMX8MP_GPU3D_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_GPU3D),
-       },
-
-       [IMX8MP_POWER_DOMAIN_MEDIAMIX] = {
-               .genpd = {
-                       .name = "mediamix",
-               },
-               .bits = {
-                       .pxx = IMX8MP_MEDIMIX_Pxx_REQ,
-                       .map = IMX8MP_MEDIAMIX_A53_DOMAIN,
-                       .hskreq = IMX8MP_MEDIAMIX_PWRDNREQN,
-                       .hskack = IMX8MP_MEDIAMIX_PWRDNACKN,
-               },
-               .pgc = BIT(IMX8MP_PGC_MEDIAMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MP_POWER_DOMAIN_VPU_G1] = {
-               .genpd = {
-                       .name = "vpu-g1",
-               },
-               .bits = {
-                       .pxx = IMX8MP_VPU_G1_Pxx_REQ,
-                       .map = IMX8MP_VPU_G1_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_VPU_G1),
-       },
-
-       [IMX8MP_POWER_DOMAIN_VPU_G2] = {
-               .genpd = {
-                       .name = "vpu-g2",
-               },
-               .bits = {
-                       .pxx = IMX8MP_VPU_G2_Pxx_REQ,
-                       .map = IMX8MP_VPU_G2_A53_DOMAIN
-               },
-               .pgc = BIT(IMX8MP_PGC_VPU_G2),
-       },
-
-       [IMX8MP_POWER_DOMAIN_VPU_VC8000E] = {
-               .genpd = {
-                       .name = "vpu-h1",
-               },
-               .bits = {
-                       .pxx = IMX8MP_VPU_VC8K_Pxx_REQ,
-                       .map = IMX8MP_VPU_VC8000E_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_VPU_VC8000E),
-       },
-
-       [IMX8MP_POWER_DOMAIN_HDMIMIX] = {
-               .genpd = {
-                       .name = "hdmimix",
-               },
-               .bits = {
-                       .pxx = IMX8MP_HDMIMIX_Pxx_REQ,
-                       .map = IMX8MP_HDMIMIX_A53_DOMAIN,
-                       .hskreq = IMX8MP_HDMIMIX_PWRDNREQN,
-                       .hskack = IMX8MP_HDMIMIX_PWRDNACKN,
-               },
-               .pgc = BIT(IMX8MP_PGC_HDMIMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MP_POWER_DOMAIN_HDMI_PHY] = {
-               .genpd = {
-                       .name = "hdmi-phy",
-               },
-               .bits = {
-                       .pxx = IMX8MP_HDMI_PHY_Pxx_REQ,
-                       .map = IMX8MP_HDMI_PHY_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_HDMI),
-       },
-
-       [IMX8MP_POWER_DOMAIN_MIPI_PHY2] = {
-               .genpd = {
-                       .name = "mipi-phy2",
-               },
-               .bits = {
-                       .pxx = IMX8MP_MIPI_PHY2_Pxx_REQ,
-                       .map = IMX8MP_MIPI_PHY2_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_MIPI2),
-       },
-
-       [IMX8MP_POWER_DOMAIN_HSIOMIX] = {
-               .genpd = {
-                       .name = "hsiomix",
-               },
-               .bits = {
-                       .pxx = IMX8MP_HSIOMIX_Pxx_REQ,
-                       .map = IMX8MP_HSIOMIX_A53_DOMAIN,
-                       .hskreq = IMX8MP_HSIOMIX_PWRDNREQN,
-                       .hskack = IMX8MP_HSIOMIX_PWRDNACKN,
-               },
-               .pgc = BIT(IMX8MP_PGC_HSIOMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MP_POWER_DOMAIN_MEDIAMIX_ISPDWP] = {
-               .genpd = {
-                       .name = "mediamix-isp-dwp",
-               },
-               .bits = {
-                       .pxx = IMX8MP_MEDIA_ISP_DWP_Pxx_REQ,
-                       .map = IMX8MP_MEDIA_ISPDWP_A53_DOMAIN,
-               },
-               .pgc = BIT(IMX8MP_PGC_MEDIA_ISP_DWP),
-       },
-};
-
-static const struct regmap_range imx8mp_yes_ranges[] = {
-               regmap_reg_range(GPC_LPCR_A_CORE_BSC,
-                                IMX8MP_GPC_PGC_CPU_MAPPING),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_NOC),
-                                GPC_PGC_SR(IMX8MP_PGC_NOC)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MIPI1),
-                                GPC_PGC_SR(IMX8MP_PGC_MIPI1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_PCIE),
-                                GPC_PGC_SR(IMX8MP_PGC_PCIE)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_USB1),
-                                GPC_PGC_SR(IMX8MP_PGC_USB1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_USB2),
-                                GPC_PGC_SR(IMX8MP_PGC_USB2)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MLMIX),
-                                GPC_PGC_SR(IMX8MP_PGC_MLMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_AUDIOMIX),
-                                GPC_PGC_SR(IMX8MP_PGC_AUDIOMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPU2D),
-                                GPC_PGC_SR(IMX8MP_PGC_GPU2D)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPUMIX),
-                                GPC_PGC_SR(IMX8MP_PGC_GPUMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPUMIX),
-                                GPC_PGC_SR(IMX8MP_PGC_VPUMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPU3D),
-                                GPC_PGC_SR(IMX8MP_PGC_GPU3D)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MEDIAMIX),
-                                GPC_PGC_SR(IMX8MP_PGC_MEDIAMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_G1),
-                                GPC_PGC_SR(IMX8MP_PGC_VPU_G1)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_G2),
-                                GPC_PGC_SR(IMX8MP_PGC_VPU_G2)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_VC8000E),
-                                GPC_PGC_SR(IMX8MP_PGC_VPU_VC8000E)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HDMIMIX),
-                                GPC_PGC_SR(IMX8MP_PGC_HDMIMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HDMI),
-                                GPC_PGC_SR(IMX8MP_PGC_HDMI)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MIPI2),
-                                GPC_PGC_SR(IMX8MP_PGC_MIPI2)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HSIOMIX),
-                                GPC_PGC_SR(IMX8MP_PGC_HSIOMIX)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MEDIA_ISP_DWP),
-                                GPC_PGC_SR(IMX8MP_PGC_MEDIA_ISP_DWP)),
-               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_DDRMIX),
-                                GPC_PGC_SR(IMX8MP_PGC_DDRMIX)),
-};
-
-static const struct regmap_access_table imx8mp_access_table = {
-       .yes_ranges     = imx8mp_yes_ranges,
-       .n_yes_ranges   = ARRAY_SIZE(imx8mp_yes_ranges),
-};
-
-static const struct imx_pgc_regs imx8mp_pgc_regs = {
-       .map = IMX8MP_GPC_PGC_CPU_MAPPING,
-       .pup = IMX8MP_GPC_PU_PGC_SW_PUP_REQ,
-       .pdn = IMX8MP_GPC_PU_PGC_SW_PDN_REQ,
-       .hsk = IMX8MP_GPC_PU_PWRHSK,
-};
-static const struct imx_pgc_domain_data imx8mp_pgc_domain_data = {
-       .domains = imx8mp_pgc_domains,
-       .domains_num = ARRAY_SIZE(imx8mp_pgc_domains),
-       .reg_access_table = &imx8mp_access_table,
-       .pgc_regs = &imx8mp_pgc_regs,
-};
-
-static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
-       [IMX8MN_POWER_DOMAIN_HSIOMIX] = {
-               .genpd = {
-                       .name = "hsiomix",
-               },
-               .bits  = {
-                       .pxx = 0, /* no power sequence control */
-                       .map = 0, /* no power sequence control */
-                       .hskreq = IMX8MN_HSIO_HSK_PWRDNREQN,
-                       .hskack = IMX8MN_HSIO_HSK_PWRDNACKN,
-               },
-               .keep_clocks = true,
-       },
-
-       [IMX8MN_POWER_DOMAIN_OTG1] = {
-               .genpd = {
-                       .name = "usb-otg1",
-                       .flags = GENPD_FLAG_ACTIVE_WAKEUP,
-               },
-               .bits  = {
-                       .pxx = IMX8MN_OTG1_SW_Pxx_REQ,
-                       .map = IMX8MN_OTG1_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MN_PGC_OTG1),
-       },
-
-       [IMX8MN_POWER_DOMAIN_GPUMIX] = {
-               .genpd = {
-                       .name = "gpumix",
-               },
-               .bits  = {
-                       .pxx = IMX8MN_GPUMIX_SW_Pxx_REQ,
-                       .map = IMX8MN_GPUMIX_A53_DOMAIN,
-                       .hskreq = IMX8MN_GPUMIX_HSK_PWRDNREQN,
-                       .hskack = IMX8MN_GPUMIX_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8MN_PGC_GPUMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MN_POWER_DOMAIN_DISPMIX] = {
-               .genpd = {
-                       .name = "dispmix",
-               },
-                       .bits  = {
-                       .pxx = IMX8MN_DISPMIX_SW_Pxx_REQ,
-                       .map = IMX8MN_DISPMIX_A53_DOMAIN,
-                       .hskreq = IMX8MN_DISPMIX_HSK_PWRDNREQN,
-                       .hskack = IMX8MN_DISPMIX_HSK_PWRDNACKN,
-               },
-               .pgc   = BIT(IMX8MN_PGC_DISPMIX),
-               .keep_clocks = true,
-       },
-
-       [IMX8MN_POWER_DOMAIN_MIPI] = {
-               .genpd = {
-                       .name = "mipi",
-               },
-                       .bits  = {
-                       .pxx = IMX8MN_MIPI_SW_Pxx_REQ,
-                       .map = IMX8MN_MIPI_A53_DOMAIN,
-               },
-               .pgc   = BIT(IMX8MN_PGC_MIPI),
-       },
-};
-
-static const struct regmap_range imx8mn_yes_ranges[] = {
-       regmap_reg_range(GPC_LPCR_A_CORE_BSC,
-                        GPC_PU_PWRHSK),
-       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_MIPI),
-                        GPC_PGC_SR(IMX8MN_PGC_MIPI)),
-       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_OTG1),
-                        GPC_PGC_SR(IMX8MN_PGC_OTG1)),
-       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_DDR1),
-                        GPC_PGC_SR(IMX8MN_PGC_DDR1)),
-       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_GPUMIX),
-                        GPC_PGC_SR(IMX8MN_PGC_GPUMIX)),
-       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_DISPMIX),
-                        GPC_PGC_SR(IMX8MN_PGC_DISPMIX)),
-};
-
-static const struct regmap_access_table imx8mn_access_table = {
-       .yes_ranges     = imx8mn_yes_ranges,
-       .n_yes_ranges   = ARRAY_SIZE(imx8mn_yes_ranges),
-};
-
-static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = {
-       .domains = imx8mn_pgc_domains,
-       .domains_num = ARRAY_SIZE(imx8mn_pgc_domains),
-       .reg_access_table = &imx8mn_access_table,
-       .pgc_regs = &imx7_pgc_regs,
-};
-
-static int imx_pgc_domain_probe(struct platform_device *pdev)
-{
-       struct imx_pgc_domain *domain = pdev->dev.platform_data;
-       int ret;
-
-       domain->dev = &pdev->dev;
-
-       domain->regulator = devm_regulator_get_optional(domain->dev, "power");
-       if (IS_ERR(domain->regulator)) {
-               if (PTR_ERR(domain->regulator) != -ENODEV)
-                       return dev_err_probe(domain->dev, PTR_ERR(domain->regulator),
-                                            "Failed to get domain's regulator\n");
-       } else if (domain->voltage) {
-               regulator_set_voltage(domain->regulator,
-                                     domain->voltage, domain->voltage);
-       }
-
-       domain->num_clks = devm_clk_bulk_get_all(domain->dev, &domain->clks);
-       if (domain->num_clks < 0)
-               return dev_err_probe(domain->dev, domain->num_clks,
-                                    "Failed to get domain's clocks\n");
-
-       domain->reset = devm_reset_control_array_get_optional_exclusive(domain->dev);
-       if (IS_ERR(domain->reset))
-               return dev_err_probe(domain->dev, PTR_ERR(domain->reset),
-                                    "Failed to get domain's resets\n");
-
-       pm_runtime_enable(domain->dev);
-
-       if (domain->bits.map)
-               regmap_update_bits(domain->regmap, domain->regs->map,
-                                  domain->bits.map, domain->bits.map);
-
-       ret = pm_genpd_init(&domain->genpd, NULL, true);
-       if (ret) {
-               dev_err(domain->dev, "Failed to init power domain\n");
-               goto out_domain_unmap;
-       }
-
-       if (IS_ENABLED(CONFIG_LOCKDEP) &&
-           of_property_read_bool(domain->dev->of_node, "power-domains"))
-               lockdep_set_subclass(&domain->genpd.mlock, 1);
-
-       ret = of_genpd_add_provider_simple(domain->dev->of_node,
-                                          &domain->genpd);
-       if (ret) {
-               dev_err(domain->dev, "Failed to add genpd provider\n");
-               goto out_genpd_remove;
-       }
-
-       return 0;
-
-out_genpd_remove:
-       pm_genpd_remove(&domain->genpd);
-out_domain_unmap:
-       if (domain->bits.map)
-               regmap_update_bits(domain->regmap, domain->regs->map,
-                                  domain->bits.map, 0);
-       pm_runtime_disable(domain->dev);
-
-       return ret;
-}
-
-static int imx_pgc_domain_remove(struct platform_device *pdev)
-{
-       struct imx_pgc_domain *domain = pdev->dev.platform_data;
-
-       of_genpd_del_provider(domain->dev->of_node);
-       pm_genpd_remove(&domain->genpd);
-
-       if (domain->bits.map)
-               regmap_update_bits(domain->regmap, domain->regs->map,
-                                  domain->bits.map, 0);
-
-       pm_runtime_disable(domain->dev);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int imx_pgc_domain_suspend(struct device *dev)
-{
-       int ret;
-
-       /*
-        * This may look strange, but is done so the generic PM_SLEEP code
-        * can power down our domain and more importantly power it up again
-        * after resume, without tripping over our usage of runtime PM to
-        * power up/down the nested domains.
-        */
-       ret = pm_runtime_get_sync(dev);
-       if (ret < 0) {
-               pm_runtime_put_noidle(dev);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int imx_pgc_domain_resume(struct device *dev)
-{
-       return pm_runtime_put(dev);
-}
-#endif
-
-static const struct dev_pm_ops imx_pgc_domain_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(imx_pgc_domain_suspend, imx_pgc_domain_resume)
-};
-
-static const struct platform_device_id imx_pgc_domain_id[] = {
-       { "imx-pgc-domain", },
-       { },
-};
-
-static struct platform_driver imx_pgc_domain_driver = {
-       .driver = {
-               .name = "imx-pgc",
-               .pm = &imx_pgc_domain_pm_ops,
-       },
-       .probe    = imx_pgc_domain_probe,
-       .remove   = imx_pgc_domain_remove,
-       .id_table = imx_pgc_domain_id,
-};
-builtin_platform_driver(imx_pgc_domain_driver)
-
-static int imx_gpcv2_probe(struct platform_device *pdev)
-{
-       const struct imx_pgc_domain_data *domain_data =
-                       of_device_get_match_data(&pdev->dev);
-
-       struct regmap_config regmap_config = {
-               .reg_bits       = 32,
-               .val_bits       = 32,
-               .reg_stride     = 4,
-               .rd_table       = domain_data->reg_access_table,
-               .wr_table       = domain_data->reg_access_table,
-               .max_register   = SZ_4K,
-       };
-       struct device *dev = &pdev->dev;
-       struct device_node *pgc_np, *np;
-       struct regmap *regmap;
-       void __iomem *base;
-       int ret;
-
-       pgc_np = of_get_child_by_name(dev->of_node, "pgc");
-       if (!pgc_np) {
-               dev_err(dev, "No power domains specified in DT\n");
-               return -EINVAL;
-       }
-
-       base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
-       if (IS_ERR(regmap)) {
-               ret = PTR_ERR(regmap);
-               dev_err(dev, "failed to init regmap (%d)\n", ret);
-               return ret;
-       }
-
-       for_each_child_of_node(pgc_np, np) {
-               struct platform_device *pd_pdev;
-               struct imx_pgc_domain *domain;
-               u32 domain_index;
-
-               if (!of_device_is_available(np))
-                       continue;
-
-               ret = of_property_read_u32(np, "reg", &domain_index);
-               if (ret) {
-                       dev_err(dev, "Failed to read 'reg' property\n");
-                       of_node_put(np);
-                       return ret;
-               }
-
-               if (domain_index >= domain_data->domains_num) {
-                       dev_warn(dev,
-                                "Domain index %d is out of bounds\n",
-                                domain_index);
-                       continue;
-               }
-
-               pd_pdev = platform_device_alloc("imx-pgc-domain",
-                                               domain_index);
-               if (!pd_pdev) {
-                       dev_err(dev, "Failed to allocate platform device\n");
-                       of_node_put(np);
-                       return -ENOMEM;
-               }
-
-               ret = platform_device_add_data(pd_pdev,
-                                              &domain_data->domains[domain_index],
-                                              sizeof(domain_data->domains[domain_index]));
-               if (ret) {
-                       platform_device_put(pd_pdev);
-                       of_node_put(np);
-                       return ret;
-               }
-
-               domain = pd_pdev->dev.platform_data;
-               domain->regmap = regmap;
-               domain->regs = domain_data->pgc_regs;
-
-               domain->genpd.power_on  = imx_pgc_power_up;
-               domain->genpd.power_off = imx_pgc_power_down;
-
-               pd_pdev->dev.parent = dev;
-               device_set_node(&pd_pdev->dev, of_fwnode_handle(np));
-
-               ret = platform_device_add(pd_pdev);
-               if (ret) {
-                       platform_device_put(pd_pdev);
-                       of_node_put(np);
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-static const struct of_device_id imx_gpcv2_dt_ids[] = {
-       { .compatible = "fsl,imx7d-gpc", .data = &imx7_pgc_domain_data, },
-       { .compatible = "fsl,imx8mm-gpc", .data = &imx8mm_pgc_domain_data, },
-       { .compatible = "fsl,imx8mn-gpc", .data = &imx8mn_pgc_domain_data, },
-       { .compatible = "fsl,imx8mp-gpc", .data = &imx8mp_pgc_domain_data, },
-       { .compatible = "fsl,imx8mq-gpc", .data = &imx8m_pgc_domain_data, },
-       { }
-};
-
-static struct platform_driver imx_gpc_driver = {
-       .driver = {
-               .name = "imx-gpcv2",
-               .of_match_table = imx_gpcv2_dt_ids,
-       },
-       .probe = imx_gpcv2_probe,
-};
-builtin_platform_driver(imx_gpc_driver)
diff --git a/drivers/genpd/imx/imx8m-blk-ctrl.c b/drivers/genpd/imx/imx8m-blk-ctrl.c
deleted file mode 100644 (file)
index cc5ef6e..0000000
+++ /dev/null
@@ -1,899 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-/*
- * Copyright 2021 Pengutronix, Lucas Stach <kernel@pengutronix.de>
- */
-
-#include <linux/bitfield.h>
-#include <linux/device.h>
-#include <linux/interconnect.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/pm_runtime.h>
-#include <linux/regmap.h>
-#include <linux/clk.h>
-
-#include <dt-bindings/power/imx8mm-power.h>
-#include <dt-bindings/power/imx8mn-power.h>
-#include <dt-bindings/power/imx8mp-power.h>
-#include <dt-bindings/power/imx8mq-power.h>
-
-#define BLK_SFT_RSTN   0x0
-#define BLK_CLK_EN     0x4
-#define BLK_MIPI_RESET_DIV     0x8 /* Mini/Nano/Plus DISPLAY_BLK_CTRL only */
-
-struct imx8m_blk_ctrl_domain;
-
-struct imx8m_blk_ctrl {
-       struct device *dev;
-       struct notifier_block power_nb;
-       struct device *bus_power_dev;
-       struct regmap *regmap;
-       struct imx8m_blk_ctrl_domain *domains;
-       struct genpd_onecell_data onecell_data;
-};
-
-struct imx8m_blk_ctrl_domain_data {
-       const char *name;
-       const char * const *clk_names;
-       const char * const *path_names;
-       const char *gpc_name;
-       int num_clks;
-       int num_paths;
-       u32 rst_mask;
-       u32 clk_mask;
-
-       /*
-        * i.MX8M Mini, Nano and Plus have a third DISPLAY_BLK_CTRL register
-        * which is used to control the reset for the MIPI Phy.
-        * Since it's only present in certain circumstances,
-        * an if-statement should be used before setting and clearing this
-        * register.
-        */
-       u32 mipi_phy_rst_mask;
-};
-
-#define DOMAIN_MAX_CLKS 4
-#define DOMAIN_MAX_PATHS 4
-
-struct imx8m_blk_ctrl_domain {
-       struct generic_pm_domain genpd;
-       const struct imx8m_blk_ctrl_domain_data *data;
-       struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
-       struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
-       struct device *power_dev;
-       struct imx8m_blk_ctrl *bc;
-       int num_paths;
-};
-
-struct imx8m_blk_ctrl_data {
-       int max_reg;
-       notifier_fn_t power_notifier_fn;
-       const struct imx8m_blk_ctrl_domain_data *domains;
-       int num_domains;
-};
-
-static inline struct imx8m_blk_ctrl_domain *
-to_imx8m_blk_ctrl_domain(struct generic_pm_domain *genpd)
-{
-       return container_of(genpd, struct imx8m_blk_ctrl_domain, genpd);
-}
-
-static int imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd)
-{
-       struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
-       const struct imx8m_blk_ctrl_domain_data *data = domain->data;
-       struct imx8m_blk_ctrl *bc = domain->bc;
-       int ret;
-
-       /* make sure bus domain is awake */
-       ret = pm_runtime_get_sync(bc->bus_power_dev);
-       if (ret < 0) {
-               pm_runtime_put_noidle(bc->bus_power_dev);
-               dev_err(bc->dev, "failed to power up bus domain\n");
-               return ret;
-       }
-
-       /* put devices into reset */
-       regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
-       if (data->mipi_phy_rst_mask)
-               regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
-
-       /* enable upstream and blk-ctrl clocks to allow reset to propagate */
-       ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
-       if (ret) {
-               dev_err(bc->dev, "failed to enable clocks\n");
-               goto bus_put;
-       }
-       regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
-
-       /* power up upstream GPC domain */
-       ret = pm_runtime_get_sync(domain->power_dev);
-       if (ret < 0) {
-               dev_err(bc->dev, "failed to power up peripheral domain\n");
-               goto clk_disable;
-       }
-
-       /* wait for reset to propagate */
-       udelay(5);
-
-       /* release reset */
-       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
-       if (data->mipi_phy_rst_mask)
-               regmap_set_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
-
-       ret = icc_bulk_set_bw(domain->num_paths, domain->paths);
-       if (ret)
-               dev_err(bc->dev, "failed to set icc bw\n");
-
-       /* disable upstream clocks */
-       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
-
-       return 0;
-
-clk_disable:
-       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
-bus_put:
-       pm_runtime_put(bc->bus_power_dev);
-
-       return ret;
-}
-
-static int imx8m_blk_ctrl_power_off(struct generic_pm_domain *genpd)
-{
-       struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
-       const struct imx8m_blk_ctrl_domain_data *data = domain->data;
-       struct imx8m_blk_ctrl *bc = domain->bc;
-
-       /* put devices into reset and disable clocks */
-       if (data->mipi_phy_rst_mask)
-               regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
-
-       regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
-       regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
-
-       /* power down upstream GPC domain */
-       pm_runtime_put(domain->power_dev);
-
-       /* allow bus domain to suspend */
-       pm_runtime_put(bc->bus_power_dev);
-
-       return 0;
-}
-
-static struct lock_class_key blk_ctrl_genpd_lock_class;
-
-static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
-{
-       const struct imx8m_blk_ctrl_data *bc_data;
-       struct device *dev = &pdev->dev;
-       struct imx8m_blk_ctrl *bc;
-       void __iomem *base;
-       int i, ret;
-
-       struct regmap_config regmap_config = {
-               .reg_bits       = 32,
-               .val_bits       = 32,
-               .reg_stride     = 4,
-       };
-
-       bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
-       if (!bc)
-               return -ENOMEM;
-
-       bc->dev = dev;
-
-       bc_data = of_device_get_match_data(dev);
-
-       base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       regmap_config.max_register = bc_data->max_reg;
-       bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
-       if (IS_ERR(bc->regmap))
-               return dev_err_probe(dev, PTR_ERR(bc->regmap),
-                                    "failed to init regmap\n");
-
-       bc->domains = devm_kcalloc(dev, bc_data->num_domains,
-                                  sizeof(struct imx8m_blk_ctrl_domain),
-                                  GFP_KERNEL);
-       if (!bc->domains)
-               return -ENOMEM;
-
-       bc->onecell_data.num_domains = bc_data->num_domains;
-       bc->onecell_data.domains =
-               devm_kcalloc(dev, bc_data->num_domains,
-                            sizeof(struct generic_pm_domain *), GFP_KERNEL);
-       if (!bc->onecell_data.domains)
-               return -ENOMEM;
-
-       bc->bus_power_dev = dev_pm_domain_attach_by_name(dev, "bus");
-       if (IS_ERR(bc->bus_power_dev)) {
-               if (PTR_ERR(bc->bus_power_dev) == -ENODEV)
-                       return dev_err_probe(dev, -EPROBE_DEFER,
-                                            "failed to attach power domain \"bus\"\n");
-               else
-                       return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
-                                            "failed to attach power domain \"bus\"\n");
-       }
-
-       for (i = 0; i < bc_data->num_domains; i++) {
-               const struct imx8m_blk_ctrl_domain_data *data = &bc_data->domains[i];
-               struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
-               int j;
-
-               domain->data = data;
-               domain->num_paths = data->num_paths;
-
-               for (j = 0; j < data->num_clks; j++)
-                       domain->clks[j].id = data->clk_names[j];
-
-               for (j = 0; j < data->num_paths; j++) {
-                       domain->paths[j].name = data->path_names[j];
-                       /* Fake value for now, just let ICC could configure NoC mode/priority */
-                       domain->paths[j].avg_bw = 1;
-                       domain->paths[j].peak_bw = 1;
-               }
-
-               ret = devm_of_icc_bulk_get(dev, data->num_paths, domain->paths);
-               if (ret) {
-                       if (ret != -EPROBE_DEFER) {
-                               dev_warn_once(dev, "Could not get interconnect paths, NoC will stay unconfigured!\n");
-                               domain->num_paths = 0;
-                       } else {
-                               dev_err_probe(dev, ret, "failed to get noc entries\n");
-                               goto cleanup_pds;
-                       }
-               }
-
-               ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
-               if (ret) {
-                       dev_err_probe(dev, ret, "failed to get clock\n");
-                       goto cleanup_pds;
-               }
-
-               domain->power_dev =
-                       dev_pm_domain_attach_by_name(dev, data->gpc_name);
-               if (IS_ERR(domain->power_dev)) {
-                       dev_err_probe(dev, PTR_ERR(domain->power_dev),
-                                     "failed to attach power domain \"%s\"\n",
-                                     data->gpc_name);
-                       ret = PTR_ERR(domain->power_dev);
-                       goto cleanup_pds;
-               }
-
-               domain->genpd.name = data->name;
-               domain->genpd.power_on = imx8m_blk_ctrl_power_on;
-               domain->genpd.power_off = imx8m_blk_ctrl_power_off;
-               domain->bc = bc;
-
-               ret = pm_genpd_init(&domain->genpd, NULL, true);
-               if (ret) {
-                       dev_err_probe(dev, ret,
-                                     "failed to init power domain \"%s\"\n",
-                                     data->gpc_name);
-                       dev_pm_domain_detach(domain->power_dev, true);
-                       goto cleanup_pds;
-               }
-
-               /*
-                * We use runtime PM to trigger power on/off of the upstream GPC
-                * domain, as a strict hierarchical parent/child power domain
-                * setup doesn't allow us to meet the sequencing requirements.
-                * This means we have nested locking of genpd locks, without the
-                * nesting being visible at the genpd level, so we need a
-                * separate lock class to make lockdep aware of the fact that
-                * this are separate domain locks that can be nested without a
-                * self-deadlock.
-                */
-               lockdep_set_class(&domain->genpd.mlock,
-                                 &blk_ctrl_genpd_lock_class);
-
-               bc->onecell_data.domains[i] = &domain->genpd;
-       }
-
-       ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
-       if (ret) {
-               dev_err_probe(dev, ret, "failed to add power domain provider\n");
-               goto cleanup_pds;
-       }
-
-       bc->power_nb.notifier_call = bc_data->power_notifier_fn;
-       ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb);
-       if (ret) {
-               dev_err_probe(dev, ret, "failed to add power notifier\n");
-               goto cleanup_provider;
-       }
-
-       dev_set_drvdata(dev, bc);
-
-       ret = devm_of_platform_populate(dev);
-       if (ret)
-               goto cleanup_provider;
-
-       return 0;
-
-cleanup_provider:
-       of_genpd_del_provider(dev->of_node);
-cleanup_pds:
-       for (i--; i >= 0; i--) {
-               pm_genpd_remove(&bc->domains[i].genpd);
-               dev_pm_domain_detach(bc->domains[i].power_dev, true);
-       }
-
-       dev_pm_domain_detach(bc->bus_power_dev, true);
-
-       return ret;
-}
-
-static int imx8m_blk_ctrl_remove(struct platform_device *pdev)
-{
-       struct imx8m_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
-       int i;
-
-       of_genpd_del_provider(pdev->dev.of_node);
-
-       for (i = 0; bc->onecell_data.num_domains; i++) {
-               struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
-
-               pm_genpd_remove(&domain->genpd);
-               dev_pm_domain_detach(domain->power_dev, true);
-       }
-
-       dev_pm_genpd_remove_notifier(bc->bus_power_dev);
-
-       dev_pm_domain_detach(bc->bus_power_dev, true);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int imx8m_blk_ctrl_suspend(struct device *dev)
-{
-       struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
-       int ret, i;
-
-       /*
-        * This may look strange, but is done so the generic PM_SLEEP code
-        * can power down our domains and more importantly power them up again
-        * after resume, without tripping over our usage of runtime PM to
-        * control the upstream GPC domains. Things happen in the right order
-        * in the system suspend/resume paths due to the device parent/child
-        * hierarchy.
-        */
-       ret = pm_runtime_get_sync(bc->bus_power_dev);
-       if (ret < 0) {
-               pm_runtime_put_noidle(bc->bus_power_dev);
-               return ret;
-       }
-
-       for (i = 0; i < bc->onecell_data.num_domains; i++) {
-               struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
-
-               ret = pm_runtime_get_sync(domain->power_dev);
-               if (ret < 0) {
-                       pm_runtime_put_noidle(domain->power_dev);
-                       goto out_fail;
-               }
-       }
-
-       return 0;
-
-out_fail:
-       for (i--; i >= 0; i--)
-               pm_runtime_put(bc->domains[i].power_dev);
-
-       pm_runtime_put(bc->bus_power_dev);
-
-       return ret;
-}
-
-static int imx8m_blk_ctrl_resume(struct device *dev)
-{
-       struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
-       int i;
-
-       for (i = 0; i < bc->onecell_data.num_domains; i++)
-               pm_runtime_put(bc->domains[i].power_dev);
-
-       pm_runtime_put(bc->bus_power_dev);
-
-       return 0;
-}
-#endif
-
-static const struct dev_pm_ops imx8m_blk_ctrl_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(imx8m_blk_ctrl_suspend, imx8m_blk_ctrl_resume)
-};
-
-static int imx8mm_vpu_power_notifier(struct notifier_block *nb,
-                                    unsigned long action, void *data)
-{
-       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
-                                                power_nb);
-
-       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
-               return NOTIFY_OK;
-
-       /*
-        * The ADB in the VPUMIX domain has no separate reset and clock
-        * enable bits, but is ungated together with the VPU clocks. To
-        * allow the handshake with the GPC to progress we put the VPUs
-        * in reset and ungate the clocks.
-        */
-       regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1) | BIT(2));
-       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1) | BIT(2));
-
-       if (action == GENPD_NOTIFY_ON) {
-               /*
-                * On power up we have no software backchannel to the GPC to
-                * wait for the ADB handshake to happen, so we just delay for a
-                * bit. On power down the GPC driver waits for the handshake.
-                */
-               udelay(5);
-
-               /* set "fuse" bits to enable the VPUs */
-               regmap_set_bits(bc->regmap, 0x8, 0xffffffff);
-               regmap_set_bits(bc->regmap, 0xc, 0xffffffff);
-               regmap_set_bits(bc->regmap, 0x10, 0xffffffff);
-               regmap_set_bits(bc->regmap, 0x14, 0xffffffff);
-       }
-
-       return NOTIFY_OK;
-}
-
-static const struct imx8m_blk_ctrl_domain_data imx8mm_vpu_blk_ctl_domain_data[] = {
-       [IMX8MM_VPUBLK_PD_G1] = {
-               .name = "vpublk-g1",
-               .clk_names = (const char *[]){ "g1", },
-               .num_clks = 1,
-               .gpc_name = "g1",
-               .rst_mask = BIT(1),
-               .clk_mask = BIT(1),
-       },
-       [IMX8MM_VPUBLK_PD_G2] = {
-               .name = "vpublk-g2",
-               .clk_names = (const char *[]){ "g2", },
-               .num_clks = 1,
-               .gpc_name = "g2",
-               .rst_mask = BIT(0),
-               .clk_mask = BIT(0),
-       },
-       [IMX8MM_VPUBLK_PD_H1] = {
-               .name = "vpublk-h1",
-               .clk_names = (const char *[]){ "h1", },
-               .num_clks = 1,
-               .gpc_name = "h1",
-               .rst_mask = BIT(2),
-               .clk_mask = BIT(2),
-       },
-};
-
-static const struct imx8m_blk_ctrl_data imx8mm_vpu_blk_ctl_dev_data = {
-       .max_reg = 0x18,
-       .power_notifier_fn = imx8mm_vpu_power_notifier,
-       .domains = imx8mm_vpu_blk_ctl_domain_data,
-       .num_domains = ARRAY_SIZE(imx8mm_vpu_blk_ctl_domain_data),
-};
-
-static const struct imx8m_blk_ctrl_domain_data imx8mp_vpu_blk_ctl_domain_data[] = {
-       [IMX8MP_VPUBLK_PD_G1] = {
-               .name = "vpublk-g1",
-               .clk_names = (const char *[]){ "g1", },
-               .num_clks = 1,
-               .gpc_name = "g1",
-               .rst_mask = BIT(1),
-               .clk_mask = BIT(1),
-               .path_names = (const char *[]){"g1"},
-               .num_paths = 1,
-       },
-       [IMX8MP_VPUBLK_PD_G2] = {
-               .name = "vpublk-g2",
-               .clk_names = (const char *[]){ "g2", },
-               .num_clks = 1,
-               .gpc_name = "g2",
-               .rst_mask = BIT(0),
-               .clk_mask = BIT(0),
-               .path_names = (const char *[]){"g2"},
-               .num_paths = 1,
-       },
-       [IMX8MP_VPUBLK_PD_VC8000E] = {
-               .name = "vpublk-vc8000e",
-               .clk_names = (const char *[]){ "vc8000e", },
-               .num_clks = 1,
-               .gpc_name = "vc8000e",
-               .rst_mask = BIT(2),
-               .clk_mask = BIT(2),
-               .path_names = (const char *[]){"vc8000e"},
-               .num_paths = 1,
-       },
-};
-
-static const struct imx8m_blk_ctrl_data imx8mp_vpu_blk_ctl_dev_data = {
-       .max_reg = 0x18,
-       .power_notifier_fn = imx8mm_vpu_power_notifier,
-       .domains = imx8mp_vpu_blk_ctl_domain_data,
-       .num_domains = ARRAY_SIZE(imx8mp_vpu_blk_ctl_domain_data),
-};
-
-static int imx8mm_disp_power_notifier(struct notifier_block *nb,
-                                     unsigned long action, void *data)
-{
-       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
-                                                power_nb);
-
-       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
-               return NOTIFY_OK;
-
-       /* Enable bus clock and deassert bus reset */
-       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(12));
-       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(6));
-
-       /*
-        * On power up we have no software backchannel to the GPC to
-        * wait for the ADB handshake to happen, so we just delay for a
-        * bit. On power down the GPC driver waits for the handshake.
-        */
-       if (action == GENPD_NOTIFY_ON)
-               udelay(5);
-
-
-       return NOTIFY_OK;
-}
-
-static const struct imx8m_blk_ctrl_domain_data imx8mm_disp_blk_ctl_domain_data[] = {
-       [IMX8MM_DISPBLK_PD_CSI_BRIDGE] = {
-               .name = "dispblk-csi-bridge",
-               .clk_names = (const char *[]){ "csi-bridge-axi", "csi-bridge-apb",
-                                              "csi-bridge-core", },
-               .num_clks = 3,
-               .gpc_name = "csi-bridge",
-               .rst_mask = BIT(0) | BIT(1) | BIT(2),
-               .clk_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5),
-       },
-       [IMX8MM_DISPBLK_PD_LCDIF] = {
-               .name = "dispblk-lcdif",
-               .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
-               .num_clks = 3,
-               .gpc_name = "lcdif",
-               .clk_mask = BIT(6) | BIT(7),
-       },
-       [IMX8MM_DISPBLK_PD_MIPI_DSI] = {
-               .name = "dispblk-mipi-dsi",
-               .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
-               .num_clks = 2,
-               .gpc_name = "mipi-dsi",
-               .rst_mask = BIT(5),
-               .clk_mask = BIT(8) | BIT(9),
-               .mipi_phy_rst_mask = BIT(17),
-       },
-       [IMX8MM_DISPBLK_PD_MIPI_CSI] = {
-               .name = "dispblk-mipi-csi",
-               .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
-               .num_clks = 2,
-               .gpc_name = "mipi-csi",
-               .rst_mask = BIT(3) | BIT(4),
-               .clk_mask = BIT(10) | BIT(11),
-               .mipi_phy_rst_mask = BIT(16),
-       },
-};
-
-static const struct imx8m_blk_ctrl_data imx8mm_disp_blk_ctl_dev_data = {
-       .max_reg = 0x2c,
-       .power_notifier_fn = imx8mm_disp_power_notifier,
-       .domains = imx8mm_disp_blk_ctl_domain_data,
-       .num_domains = ARRAY_SIZE(imx8mm_disp_blk_ctl_domain_data),
-};
-
-
-static int imx8mn_disp_power_notifier(struct notifier_block *nb,
-                                     unsigned long action, void *data)
-{
-       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
-                                                power_nb);
-
-       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
-               return NOTIFY_OK;
-
-       /* Enable bus clock and deassert bus reset */
-       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8));
-       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8));
-
-       /*
-        * On power up we have no software backchannel to the GPC to
-        * wait for the ADB handshake to happen, so we just delay for a
-        * bit. On power down the GPC driver waits for the handshake.
-        */
-       if (action == GENPD_NOTIFY_ON)
-               udelay(5);
-
-
-       return NOTIFY_OK;
-}
-
-static const struct imx8m_blk_ctrl_domain_data imx8mn_disp_blk_ctl_domain_data[] = {
-       [IMX8MN_DISPBLK_PD_MIPI_DSI] = {
-               .name = "dispblk-mipi-dsi",
-               .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
-               .num_clks = 2,
-               .gpc_name = "mipi-dsi",
-               .rst_mask = BIT(0) | BIT(1),
-               .clk_mask = BIT(0) | BIT(1),
-               .mipi_phy_rst_mask = BIT(17),
-       },
-       [IMX8MN_DISPBLK_PD_MIPI_CSI] = {
-               .name = "dispblk-mipi-csi",
-               .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
-               .num_clks = 2,
-               .gpc_name = "mipi-csi",
-               .rst_mask = BIT(2) | BIT(3),
-               .clk_mask = BIT(2) | BIT(3),
-               .mipi_phy_rst_mask = BIT(16),
-       },
-       [IMX8MN_DISPBLK_PD_LCDIF] = {
-               .name = "dispblk-lcdif",
-               .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
-               .num_clks = 3,
-               .gpc_name = "lcdif",
-               .rst_mask = BIT(4) | BIT(5),
-               .clk_mask = BIT(4) | BIT(5),
-       },
-       [IMX8MN_DISPBLK_PD_ISI] = {
-               .name = "dispblk-isi",
-               .clk_names = (const char *[]){ "disp_axi", "disp_apb", "disp_axi_root",
-                                               "disp_apb_root"},
-               .num_clks = 4,
-               .gpc_name = "isi",
-               .rst_mask = BIT(6) | BIT(7),
-               .clk_mask = BIT(6) | BIT(7),
-       },
-};
-
-static const struct imx8m_blk_ctrl_data imx8mn_disp_blk_ctl_dev_data = {
-       .max_reg = 0x84,
-       .power_notifier_fn = imx8mn_disp_power_notifier,
-       .domains = imx8mn_disp_blk_ctl_domain_data,
-       .num_domains = ARRAY_SIZE(imx8mn_disp_blk_ctl_domain_data),
-};
-
-#define LCDIF_ARCACHE_CTRL     0x4c
-#define  LCDIF_1_RD_HURRY      GENMASK(15, 13)
-#define  LCDIF_0_RD_HURRY      GENMASK(12, 10)
-
-static int imx8mp_media_power_notifier(struct notifier_block *nb,
-                               unsigned long action, void *data)
-{
-       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
-                                                power_nb);
-
-       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
-               return NOTIFY_OK;
-
-       /* Enable bus clock and deassert bus reset */
-       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8));
-       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8));
-
-       if (action == GENPD_NOTIFY_ON) {
-               /*
-                * On power up we have no software backchannel to the GPC to
-                * wait for the ADB handshake to happen, so we just delay for a
-                * bit. On power down the GPC driver waits for the handshake.
-                */
-               udelay(5);
-
-               /*
-                * Set panic read hurry level for both LCDIF interfaces to
-                * maximum priority to minimize chances of display FIFO
-                * underflow.
-                */
-               regmap_set_bits(bc->regmap, LCDIF_ARCACHE_CTRL,
-                               FIELD_PREP(LCDIF_1_RD_HURRY, 7) |
-                               FIELD_PREP(LCDIF_0_RD_HURRY, 7));
-       }
-
-       return NOTIFY_OK;
-}
-
-/*
- * From i.MX 8M Plus Applications Processor Reference Manual, Rev. 1,
- * section 13.2.2, 13.2.3
- * isp-ahb and dwe are not in Figure 13-5. Media BLK_CTRL Clocks
- */
-static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[] = {
-       [IMX8MP_MEDIABLK_PD_MIPI_DSI_1] = {
-               .name = "mediablk-mipi-dsi-1",
-               .clk_names = (const char *[]){ "apb", "phy", },
-               .num_clks = 2,
-               .gpc_name = "mipi-dsi1",
-               .rst_mask = BIT(0) | BIT(1),
-               .clk_mask = BIT(0) | BIT(1),
-               .mipi_phy_rst_mask = BIT(17),
-       },
-       [IMX8MP_MEDIABLK_PD_MIPI_CSI2_1] = {
-               .name = "mediablk-mipi-csi2-1",
-               .clk_names = (const char *[]){ "apb", "cam1" },
-               .num_clks = 2,
-               .gpc_name = "mipi-csi1",
-               .rst_mask = BIT(2) | BIT(3),
-               .clk_mask = BIT(2) | BIT(3),
-               .mipi_phy_rst_mask = BIT(16),
-       },
-       [IMX8MP_MEDIABLK_PD_LCDIF_1] = {
-               .name = "mediablk-lcdif-1",
-               .clk_names = (const char *[]){ "disp1", "apb", "axi", },
-               .num_clks = 3,
-               .gpc_name = "lcdif1",
-               .rst_mask = BIT(4) | BIT(5) | BIT(23),
-               .clk_mask = BIT(4) | BIT(5) | BIT(23),
-               .path_names = (const char *[]){"lcdif-rd", "lcdif-wr"},
-               .num_paths = 2,
-       },
-       [IMX8MP_MEDIABLK_PD_ISI] = {
-               .name = "mediablk-isi",
-               .clk_names = (const char *[]){ "axi", "apb" },
-               .num_clks = 2,
-               .gpc_name = "isi",
-               .rst_mask = BIT(6) | BIT(7),
-               .clk_mask = BIT(6) | BIT(7),
-               .path_names = (const char *[]){"isi0", "isi1", "isi2"},
-               .num_paths = 3,
-       },
-       [IMX8MP_MEDIABLK_PD_MIPI_CSI2_2] = {
-               .name = "mediablk-mipi-csi2-2",
-               .clk_names = (const char *[]){ "apb", "cam2" },
-               .num_clks = 2,
-               .gpc_name = "mipi-csi2",
-               .rst_mask = BIT(9) | BIT(10),
-               .clk_mask = BIT(9) | BIT(10),
-               .mipi_phy_rst_mask = BIT(30),
-       },
-       [IMX8MP_MEDIABLK_PD_LCDIF_2] = {
-               .name = "mediablk-lcdif-2",
-               .clk_names = (const char *[]){ "disp2", "apb", "axi", },
-               .num_clks = 3,
-               .gpc_name = "lcdif2",
-               .rst_mask = BIT(11) | BIT(12) | BIT(24),
-               .clk_mask = BIT(11) | BIT(12) | BIT(24),
-               .path_names = (const char *[]){"lcdif-rd", "lcdif-wr"},
-               .num_paths = 2,
-       },
-       [IMX8MP_MEDIABLK_PD_ISP] = {
-               .name = "mediablk-isp",
-               .clk_names = (const char *[]){ "isp", "axi", "apb" },
-               .num_clks = 3,
-               .gpc_name = "isp",
-               .rst_mask = BIT(16) | BIT(17) | BIT(18),
-               .clk_mask = BIT(16) | BIT(17) | BIT(18),
-               .path_names = (const char *[]){"isp0", "isp1"},
-               .num_paths = 2,
-       },
-       [IMX8MP_MEDIABLK_PD_DWE] = {
-               .name = "mediablk-dwe",
-               .clk_names = (const char *[]){ "axi", "apb" },
-               .num_clks = 2,
-               .gpc_name = "dwe",
-               .rst_mask = BIT(19) | BIT(20) | BIT(21),
-               .clk_mask = BIT(19) | BIT(20) | BIT(21),
-               .path_names = (const char *[]){"dwe"},
-               .num_paths = 1,
-       },
-       [IMX8MP_MEDIABLK_PD_MIPI_DSI_2] = {
-               .name = "mediablk-mipi-dsi-2",
-               .clk_names = (const char *[]){ "phy", },
-               .num_clks = 1,
-               .gpc_name = "mipi-dsi2",
-               .rst_mask = BIT(22),
-               .clk_mask = BIT(22),
-               .mipi_phy_rst_mask = BIT(29),
-       },
-};
-
-static const struct imx8m_blk_ctrl_data imx8mp_media_blk_ctl_dev_data = {
-       .max_reg = 0x138,
-       .power_notifier_fn = imx8mp_media_power_notifier,
-       .domains = imx8mp_media_blk_ctl_domain_data,
-       .num_domains = ARRAY_SIZE(imx8mp_media_blk_ctl_domain_data),
-};
-
-static int imx8mq_vpu_power_notifier(struct notifier_block *nb,
-                                    unsigned long action, void *data)
-{
-       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
-                                                power_nb);
-
-       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
-               return NOTIFY_OK;
-
-       /*
-        * The ADB in the VPUMIX domain has no separate reset and clock
-        * enable bits, but is ungated and reset together with the VPUs. The
-        * reset and clock enable inputs to the ADB is a logical OR of the
-        * VPU bits. In order to set the G2 fuse bits, the G2 clock must
-        * also be enabled.
-        */
-       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1));
-       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1));
-
-       if (action == GENPD_NOTIFY_ON) {
-               /*
-                * On power up we have no software backchannel to the GPC to
-                * wait for the ADB handshake to happen, so we just delay for a
-                * bit. On power down the GPC driver waits for the handshake.
-                */
-               udelay(5);
-
-               /* set "fuse" bits to enable the VPUs */
-               regmap_set_bits(bc->regmap, 0x8, 0xffffffff);
-               regmap_set_bits(bc->regmap, 0xc, 0xffffffff);
-               regmap_set_bits(bc->regmap, 0x10, 0xffffffff);
-       }
-
-       return NOTIFY_OK;
-}
-
-static const struct imx8m_blk_ctrl_domain_data imx8mq_vpu_blk_ctl_domain_data[] = {
-       [IMX8MQ_VPUBLK_PD_G1] = {
-               .name = "vpublk-g1",
-               .clk_names = (const char *[]){ "g1", },
-               .num_clks = 1,
-               .gpc_name = "g1",
-               .rst_mask = BIT(1),
-               .clk_mask = BIT(1),
-       },
-       [IMX8MQ_VPUBLK_PD_G2] = {
-               .name = "vpublk-g2",
-               .clk_names = (const char *[]){ "g2", },
-               .num_clks = 1,
-               .gpc_name = "g2",
-               .rst_mask = BIT(0),
-               .clk_mask = BIT(0),
-       },
-};
-
-static const struct imx8m_blk_ctrl_data imx8mq_vpu_blk_ctl_dev_data = {
-       .max_reg = 0x14,
-       .power_notifier_fn = imx8mq_vpu_power_notifier,
-       .domains = imx8mq_vpu_blk_ctl_domain_data,
-       .num_domains = ARRAY_SIZE(imx8mq_vpu_blk_ctl_domain_data),
-};
-
-static const struct of_device_id imx8m_blk_ctrl_of_match[] = {
-       {
-               .compatible = "fsl,imx8mm-vpu-blk-ctrl",
-               .data = &imx8mm_vpu_blk_ctl_dev_data
-       }, {
-               .compatible = "fsl,imx8mm-disp-blk-ctrl",
-               .data = &imx8mm_disp_blk_ctl_dev_data
-       }, {
-               .compatible = "fsl,imx8mn-disp-blk-ctrl",
-               .data = &imx8mn_disp_blk_ctl_dev_data
-       }, {
-               .compatible = "fsl,imx8mp-media-blk-ctrl",
-               .data = &imx8mp_media_blk_ctl_dev_data
-       }, {
-               .compatible = "fsl,imx8mq-vpu-blk-ctrl",
-               .data = &imx8mq_vpu_blk_ctl_dev_data
-       }, {
-               .compatible = "fsl,imx8mp-vpu-blk-ctrl",
-               .data = &imx8mp_vpu_blk_ctl_dev_data
-       }, {
-               /* Sentinel */
-       }
-};
-MODULE_DEVICE_TABLE(of, imx8m_blk_ctrl_of_match);
-
-static struct platform_driver imx8m_blk_ctrl_driver = {
-       .probe = imx8m_blk_ctrl_probe,
-       .remove = imx8m_blk_ctrl_remove,
-       .driver = {
-               .name = "imx8m-blk-ctrl",
-               .pm = &imx8m_blk_ctrl_pm_ops,
-               .of_match_table = imx8m_blk_ctrl_of_match,
-       },
-};
-module_platform_driver(imx8m_blk_ctrl_driver);
-MODULE_LICENSE("GPL");
diff --git a/drivers/genpd/imx/imx8mp-blk-ctrl.c b/drivers/genpd/imx/imx8mp-blk-ctrl.c
deleted file mode 100644 (file)
index c6ac32c..0000000
+++ /dev/null
@@ -1,867 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-/*
- * Copyright 2022 Pengutronix, Lucas Stach <kernel@pengutronix.de>
- */
-
-#include <linux/bitfield.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/device.h>
-#include <linux/interconnect.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/pm_runtime.h>
-#include <linux/regmap.h>
-
-#include <dt-bindings/power/imx8mp-power.h>
-
-#define GPR_REG0               0x0
-#define  PCIE_CLOCK_MODULE_EN  BIT(0)
-#define  USB_CLOCK_MODULE_EN   BIT(1)
-#define  PCIE_PHY_APB_RST      BIT(4)
-#define  PCIE_PHY_INIT_RST     BIT(5)
-#define GPR_REG1               0x4
-#define  PLL_LOCK              BIT(13)
-#define GPR_REG2               0x8
-#define  P_PLL_MASK            GENMASK(5, 0)
-#define  M_PLL_MASK            GENMASK(15, 6)
-#define  S_PLL_MASK            GENMASK(18, 16)
-#define GPR_REG3               0xc
-#define  PLL_CKE               BIT(17)
-#define  PLL_RST               BIT(31)
-
-struct imx8mp_blk_ctrl_domain;
-
-struct imx8mp_blk_ctrl {
-       struct device *dev;
-       struct notifier_block power_nb;
-       struct device *bus_power_dev;
-       struct regmap *regmap;
-       struct imx8mp_blk_ctrl_domain *domains;
-       struct genpd_onecell_data onecell_data;
-       void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
-       void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
-};
-
-struct imx8mp_blk_ctrl_domain_data {
-       const char *name;
-       const char * const *clk_names;
-       int num_clks;
-       const char * const *path_names;
-       int num_paths;
-       const char *gpc_name;
-};
-
-#define DOMAIN_MAX_CLKS 2
-#define DOMAIN_MAX_PATHS 3
-
-struct imx8mp_blk_ctrl_domain {
-       struct generic_pm_domain genpd;
-       const struct imx8mp_blk_ctrl_domain_data *data;
-       struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
-       struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
-       struct device *power_dev;
-       struct imx8mp_blk_ctrl *bc;
-       int num_paths;
-       int id;
-};
-
-struct imx8mp_blk_ctrl_data {
-       int max_reg;
-       int (*probe) (struct imx8mp_blk_ctrl *bc);
-       notifier_fn_t power_notifier_fn;
-       void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
-       void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
-       const struct imx8mp_blk_ctrl_domain_data *domains;
-       int num_domains;
-};
-
-static inline struct imx8mp_blk_ctrl_domain *
-to_imx8mp_blk_ctrl_domain(struct generic_pm_domain *genpd)
-{
-       return container_of(genpd, struct imx8mp_blk_ctrl_domain, genpd);
-}
-
-struct clk_hsio_pll {
-       struct clk_hw   hw;
-       struct regmap *regmap;
-};
-
-static inline struct clk_hsio_pll *to_clk_hsio_pll(struct clk_hw *hw)
-{
-       return container_of(hw, struct clk_hsio_pll, hw);
-}
-
-static int clk_hsio_pll_prepare(struct clk_hw *hw)
-{
-       struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
-       u32 val;
-
-       /* set the PLL configuration */
-       regmap_update_bits(clk->regmap, GPR_REG2,
-                          P_PLL_MASK | M_PLL_MASK | S_PLL_MASK,
-                          FIELD_PREP(P_PLL_MASK, 12) |
-                          FIELD_PREP(M_PLL_MASK, 800) |
-                          FIELD_PREP(S_PLL_MASK, 4));
-
-       /* de-assert PLL reset */
-       regmap_update_bits(clk->regmap, GPR_REG3, PLL_RST, PLL_RST);
-
-       /* enable PLL */
-       regmap_update_bits(clk->regmap, GPR_REG3, PLL_CKE, PLL_CKE);
-
-       return regmap_read_poll_timeout(clk->regmap, GPR_REG1, val,
-                                       val & PLL_LOCK, 10, 100);
-}
-
-static void clk_hsio_pll_unprepare(struct clk_hw *hw)
-{
-       struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
-
-       regmap_update_bits(clk->regmap, GPR_REG3, PLL_RST | PLL_CKE, 0);
-}
-
-static int clk_hsio_pll_is_prepared(struct clk_hw *hw)
-{
-       struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
-
-       return regmap_test_bits(clk->regmap, GPR_REG1, PLL_LOCK);
-}
-
-static unsigned long clk_hsio_pll_recalc_rate(struct clk_hw *hw,
-                                             unsigned long parent_rate)
-{
-       return 100000000;
-}
-
-static const struct clk_ops clk_hsio_pll_ops = {
-       .prepare = clk_hsio_pll_prepare,
-       .unprepare = clk_hsio_pll_unprepare,
-       .is_prepared = clk_hsio_pll_is_prepared,
-       .recalc_rate = clk_hsio_pll_recalc_rate,
-};
-
-static int imx8mp_hsio_blk_ctrl_probe(struct imx8mp_blk_ctrl *bc)
-{
-       struct clk_hsio_pll *clk_hsio_pll;
-       struct clk_hw *hw;
-       struct clk_init_data init = {};
-       int ret;
-
-       clk_hsio_pll = devm_kzalloc(bc->dev, sizeof(*clk_hsio_pll), GFP_KERNEL);
-       if (!clk_hsio_pll)
-               return -ENOMEM;
-
-       init.name = "hsio_pll";
-       init.ops = &clk_hsio_pll_ops;
-       init.parent_names = (const char *[]){"osc_24m"};
-       init.num_parents = 1;
-
-       clk_hsio_pll->regmap = bc->regmap;
-       clk_hsio_pll->hw.init = &init;
-
-       hw = &clk_hsio_pll->hw;
-       ret = devm_clk_hw_register(bc->bus_power_dev, hw);
-       if (ret)
-               return ret;
-
-       return devm_of_clk_add_hw_provider(bc->dev, of_clk_hw_simple_get, hw);
-}
-
-static void imx8mp_hsio_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
-                                         struct imx8mp_blk_ctrl_domain *domain)
-{
-       switch (domain->id) {
-       case IMX8MP_HSIOBLK_PD_USB:
-               regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
-               break;
-       case IMX8MP_HSIOBLK_PD_PCIE:
-               regmap_set_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
-               break;
-       case IMX8MP_HSIOBLK_PD_PCIE_PHY:
-               regmap_set_bits(bc->regmap, GPR_REG0,
-                               PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST);
-               break;
-       default:
-               break;
-       }
-}
-
-static void imx8mp_hsio_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
-                                          struct imx8mp_blk_ctrl_domain *domain)
-{
-       switch (domain->id) {
-       case IMX8MP_HSIOBLK_PD_USB:
-               regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
-               break;
-       case IMX8MP_HSIOBLK_PD_PCIE:
-               regmap_clear_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
-               break;
-       case IMX8MP_HSIOBLK_PD_PCIE_PHY:
-               regmap_clear_bits(bc->regmap, GPR_REG0,
-                                 PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST);
-               break;
-       default:
-               break;
-       }
-}
-
-static int imx8mp_hsio_power_notifier(struct notifier_block *nb,
-                                     unsigned long action, void *data)
-{
-       struct imx8mp_blk_ctrl *bc = container_of(nb, struct imx8mp_blk_ctrl,
-                                                power_nb);
-       struct clk_bulk_data *usb_clk = bc->domains[IMX8MP_HSIOBLK_PD_USB].clks;
-       int num_clks = bc->domains[IMX8MP_HSIOBLK_PD_USB].data->num_clks;
-       int ret;
-
-       switch (action) {
-       case GENPD_NOTIFY_ON:
-               /*
-                * enable USB clock for a moment for the power-on ADB handshake
-                * to proceed
-                */
-               ret = clk_bulk_prepare_enable(num_clks, usb_clk);
-               if (ret)
-                       return NOTIFY_BAD;
-               regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
-
-               udelay(5);
-
-               regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
-               clk_bulk_disable_unprepare(num_clks, usb_clk);
-               break;
-       case GENPD_NOTIFY_PRE_OFF:
-               /* enable USB clock for the power-down ADB handshake to work */
-               ret = clk_bulk_prepare_enable(num_clks, usb_clk);
-               if (ret)
-                       return NOTIFY_BAD;
-
-               regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
-               break;
-       case GENPD_NOTIFY_OFF:
-               clk_bulk_disable_unprepare(num_clks, usb_clk);
-               break;
-       default:
-               break;
-       }
-
-       return NOTIFY_OK;
-}
-
-static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = {
-       [IMX8MP_HSIOBLK_PD_USB] = {
-               .name = "hsioblk-usb",
-               .clk_names = (const char *[]){ "usb" },
-               .num_clks = 1,
-               .gpc_name = "usb",
-               .path_names = (const char *[]){"usb1", "usb2"},
-               .num_paths = 2,
-       },
-       [IMX8MP_HSIOBLK_PD_USB_PHY1] = {
-               .name = "hsioblk-usb-phy1",
-               .gpc_name = "usb-phy1",
-       },
-       [IMX8MP_HSIOBLK_PD_USB_PHY2] = {
-               .name = "hsioblk-usb-phy2",
-               .gpc_name = "usb-phy2",
-       },
-       [IMX8MP_HSIOBLK_PD_PCIE] = {
-               .name = "hsioblk-pcie",
-               .clk_names = (const char *[]){ "pcie" },
-               .num_clks = 1,
-               .gpc_name = "pcie",
-               .path_names = (const char *[]){"noc-pcie", "pcie"},
-               .num_paths = 2,
-       },
-       [IMX8MP_HSIOBLK_PD_PCIE_PHY] = {
-               .name = "hsioblk-pcie-phy",
-               .gpc_name = "pcie-phy",
-       },
-};
-
-static const struct imx8mp_blk_ctrl_data imx8mp_hsio_blk_ctl_dev_data = {
-       .max_reg = 0x24,
-       .probe = imx8mp_hsio_blk_ctrl_probe,
-       .power_on = imx8mp_hsio_blk_ctrl_power_on,
-       .power_off = imx8mp_hsio_blk_ctrl_power_off,
-       .power_notifier_fn = imx8mp_hsio_power_notifier,
-       .domains = imx8mp_hsio_domain_data,
-       .num_domains = ARRAY_SIZE(imx8mp_hsio_domain_data),
-};
-
-#define HDMI_RTX_RESET_CTL0    0x20
-#define HDMI_RTX_CLK_CTL0      0x40
-#define HDMI_RTX_CLK_CTL1      0x50
-#define HDMI_RTX_CLK_CTL2      0x60
-#define HDMI_RTX_CLK_CTL3      0x70
-#define HDMI_RTX_CLK_CTL4      0x80
-#define HDMI_TX_CONTROL0       0x200
-#define  HDMI_LCDIF_NOC_HURRY_MASK             GENMASK(14, 12)
-
-static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
-                                         struct imx8mp_blk_ctrl_domain *domain)
-{
-       switch (domain->id) {
-       case IMX8MP_HDMIBLK_PD_IRQSTEER:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(9));
-               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(16));
-               break;
-       case IMX8MP_HDMIBLK_PD_LCDIF:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
-                               BIT(16) | BIT(17) | BIT(18) |
-                               BIT(19) | BIT(20));
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11));
-               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
-                               BIT(4) | BIT(5) | BIT(6));
-               regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0,
-                               FIELD_PREP(HDMI_LCDIF_NOC_HURRY_MASK, 7));
-               break;
-       case IMX8MP_HDMIBLK_PD_PAI:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17));
-               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(18));
-               break;
-       case IMX8MP_HDMIBLK_PD_PVI:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(28));
-               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(22));
-               break;
-       case IMX8MP_HDMIBLK_PD_TRNG:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(27) | BIT(30));
-               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(20));
-               break;
-       case IMX8MP_HDMIBLK_PD_HDMI_TX:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
-                               BIT(2) | BIT(4) | BIT(5));
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1,
-                               BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) |
-                               BIT(18) | BIT(19) | BIT(20) | BIT(21));
-               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
-                               BIT(7) | BIT(10) | BIT(11));
-               regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1));
-               break;
-       case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7));
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
-               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
-               regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
-               break;
-       case IMX8MP_HDMIBLK_PD_HDCP:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11));
-               break;
-       case IMX8MP_HDMIBLK_PD_HRV:
-               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5));
-               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15));
-               break;
-       default:
-               break;
-       }
-}
-
-static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
-                                          struct imx8mp_blk_ctrl_domain *domain)
-{
-       switch (domain->id) {
-       case IMX8MP_HDMIBLK_PD_IRQSTEER:
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(9));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(16));
-               break;
-       case IMX8MP_HDMIBLK_PD_LCDIF:
-               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
-                                 BIT(4) | BIT(5) | BIT(6));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
-                                 BIT(16) | BIT(17) | BIT(18) |
-                                 BIT(19) | BIT(20));
-               break;
-       case IMX8MP_HDMIBLK_PD_PAI:
-               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(18));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17));
-               break;
-       case IMX8MP_HDMIBLK_PD_PVI:
-               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(22));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(28));
-               break;
-       case IMX8MP_HDMIBLK_PD_TRNG:
-               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(20));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(27) | BIT(30));
-               break;
-       case IMX8MP_HDMIBLK_PD_HDMI_TX:
-               regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
-                                 BIT(7) | BIT(10) | BIT(11));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1,
-                                 BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) |
-                                 BIT(18) | BIT(19) | BIT(20) | BIT(21));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
-                                 BIT(2) | BIT(4) | BIT(5));
-               break;
-       case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY:
-               regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
-               break;
-       case IMX8MP_HDMIBLK_PD_HDCP:
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11));
-               break;
-       case IMX8MP_HDMIBLK_PD_HRV:
-               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15));
-               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5));
-               break;
-       default:
-               break;
-       }
-}
-
-static int imx8mp_hdmi_power_notifier(struct notifier_block *nb,
-                                     unsigned long action, void *data)
-{
-       struct imx8mp_blk_ctrl *bc = container_of(nb, struct imx8mp_blk_ctrl,
-                                                power_nb);
-
-       if (action != GENPD_NOTIFY_ON)
-               return NOTIFY_OK;
-
-       /*
-        * Contrary to other blk-ctrls the reset and clock don't clear when the
-        * power domain is powered down. To ensure the proper reset pulsing,
-        * first clear them all to asserted state, then enable the bus clocks
-        * and then release the ADB reset.
-        */
-       regmap_write(bc->regmap, HDMI_RTX_RESET_CTL0, 0x0);
-       regmap_write(bc->regmap, HDMI_RTX_CLK_CTL0, 0x0);
-       regmap_write(bc->regmap, HDMI_RTX_CLK_CTL1, 0x0);
-       regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
-                       BIT(0) | BIT(1) | BIT(10));
-       regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(0));
-
-       /*
-        * On power up we have no software backchannel to the GPC to
-        * wait for the ADB handshake to happen, so we just delay for a
-        * bit. On power down the GPC driver waits for the handshake.
-        */
-       udelay(5);
-
-       return NOTIFY_OK;
-}
-
-static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = {
-       [IMX8MP_HDMIBLK_PD_IRQSTEER] = {
-               .name = "hdmiblk-irqsteer",
-               .clk_names = (const char *[]){ "apb" },
-               .num_clks = 1,
-               .gpc_name = "irqsteer",
-       },
-       [IMX8MP_HDMIBLK_PD_LCDIF] = {
-               .name = "hdmiblk-lcdif",
-               .clk_names = (const char *[]){ "axi", "apb" },
-               .num_clks = 2,
-               .gpc_name = "lcdif",
-               .path_names = (const char *[]){"lcdif-hdmi"},
-               .num_paths = 1,
-       },
-       [IMX8MP_HDMIBLK_PD_PAI] = {
-               .name = "hdmiblk-pai",
-               .clk_names = (const char *[]){ "apb" },
-               .num_clks = 1,
-               .gpc_name = "pai",
-       },
-       [IMX8MP_HDMIBLK_PD_PVI] = {
-               .name = "hdmiblk-pvi",
-               .clk_names = (const char *[]){ "apb" },
-               .num_clks = 1,
-               .gpc_name = "pvi",
-       },
-       [IMX8MP_HDMIBLK_PD_TRNG] = {
-               .name = "hdmiblk-trng",
-               .clk_names = (const char *[]){ "apb" },
-               .num_clks = 1,
-               .gpc_name = "trng",
-       },
-       [IMX8MP_HDMIBLK_PD_HDMI_TX] = {
-               .name = "hdmiblk-hdmi-tx",
-               .clk_names = (const char *[]){ "apb", "ref_266m" },
-               .num_clks = 2,
-               .gpc_name = "hdmi-tx",
-       },
-       [IMX8MP_HDMIBLK_PD_HDMI_TX_PHY] = {
-               .name = "hdmiblk-hdmi-tx-phy",
-               .clk_names = (const char *[]){ "apb", "ref_24m" },
-               .num_clks = 2,
-               .gpc_name = "hdmi-tx-phy",
-       },
-       [IMX8MP_HDMIBLK_PD_HRV] = {
-               .name = "hdmiblk-hrv",
-               .clk_names = (const char *[]){ "axi", "apb" },
-               .num_clks = 2,
-               .gpc_name = "hrv",
-               .path_names = (const char *[]){"hrv"},
-               .num_paths = 1,
-       },
-       [IMX8MP_HDMIBLK_PD_HDCP] = {
-               .name = "hdmiblk-hdcp",
-               .clk_names = (const char *[]){ "axi", "apb" },
-               .num_clks = 2,
-               .gpc_name = "hdcp",
-               .path_names = (const char *[]){"hdcp"},
-               .num_paths = 1,
-       },
-};
-
-static const struct imx8mp_blk_ctrl_data imx8mp_hdmi_blk_ctl_dev_data = {
-       .max_reg = 0x23c,
-       .power_on = imx8mp_hdmi_blk_ctrl_power_on,
-       .power_off = imx8mp_hdmi_blk_ctrl_power_off,
-       .power_notifier_fn = imx8mp_hdmi_power_notifier,
-       .domains = imx8mp_hdmi_domain_data,
-       .num_domains = ARRAY_SIZE(imx8mp_hdmi_domain_data),
-};
-
-static int imx8mp_blk_ctrl_power_on(struct generic_pm_domain *genpd)
-{
-       struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd);
-       const struct imx8mp_blk_ctrl_domain_data *data = domain->data;
-       struct imx8mp_blk_ctrl *bc = domain->bc;
-       int ret;
-
-       /* make sure bus domain is awake */
-       ret = pm_runtime_resume_and_get(bc->bus_power_dev);
-       if (ret < 0) {
-               dev_err(bc->dev, "failed to power up bus domain\n");
-               return ret;
-       }
-
-       /* enable upstream clocks */
-       ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
-       if (ret) {
-               dev_err(bc->dev, "failed to enable clocks\n");
-               goto bus_put;
-       }
-
-       /* domain specific blk-ctrl manipulation */
-       bc->power_on(bc, domain);
-
-       /* power up upstream GPC domain */
-       ret = pm_runtime_resume_and_get(domain->power_dev);
-       if (ret < 0) {
-               dev_err(bc->dev, "failed to power up peripheral domain\n");
-               goto clk_disable;
-       }
-
-       ret = icc_bulk_set_bw(domain->num_paths, domain->paths);
-       if (ret)
-               dev_err(bc->dev, "failed to set icc bw\n");
-
-       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
-
-       return 0;
-
-clk_disable:
-       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
-bus_put:
-       pm_runtime_put(bc->bus_power_dev);
-
-       return ret;
-}
-
-static int imx8mp_blk_ctrl_power_off(struct generic_pm_domain *genpd)
-{
-       struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd);
-       const struct imx8mp_blk_ctrl_domain_data *data = domain->data;
-       struct imx8mp_blk_ctrl *bc = domain->bc;
-       int ret;
-
-       ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
-       if (ret) {
-               dev_err(bc->dev, "failed to enable clocks\n");
-               return ret;
-       }
-
-       /* domain specific blk-ctrl manipulation */
-       bc->power_off(bc, domain);
-
-       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
-
-       /* power down upstream GPC domain */
-       pm_runtime_put(domain->power_dev);
-
-       /* allow bus domain to suspend */
-       pm_runtime_put(bc->bus_power_dev);
-
-       return 0;
-}
-
-static struct lock_class_key blk_ctrl_genpd_lock_class;
-
-static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
-{
-       const struct imx8mp_blk_ctrl_data *bc_data;
-       struct device *dev = &pdev->dev;
-       struct imx8mp_blk_ctrl *bc;
-       void __iomem *base;
-       int num_domains, i, ret;
-
-       struct regmap_config regmap_config = {
-               .reg_bits       = 32,
-               .val_bits       = 32,
-               .reg_stride     = 4,
-       };
-
-       bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
-       if (!bc)
-               return -ENOMEM;
-
-       bc->dev = dev;
-
-       bc_data = of_device_get_match_data(dev);
-       num_domains = bc_data->num_domains;
-
-       base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       regmap_config.max_register = bc_data->max_reg;
-       bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
-       if (IS_ERR(bc->regmap))
-               return dev_err_probe(dev, PTR_ERR(bc->regmap),
-                                    "failed to init regmap\n");
-
-       bc->domains = devm_kcalloc(dev, num_domains,
-                                  sizeof(struct imx8mp_blk_ctrl_domain),
-                                  GFP_KERNEL);
-       if (!bc->domains)
-               return -ENOMEM;
-
-       bc->onecell_data.num_domains = num_domains;
-       bc->onecell_data.domains =
-               devm_kcalloc(dev, num_domains,
-                            sizeof(struct generic_pm_domain *), GFP_KERNEL);
-       if (!bc->onecell_data.domains)
-               return -ENOMEM;
-
-       bc->bus_power_dev = dev_pm_domain_attach_by_name(dev, "bus");
-       if (IS_ERR(bc->bus_power_dev))
-               return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
-                                    "failed to attach bus power domain\n");
-
-       bc->power_off = bc_data->power_off;
-       bc->power_on = bc_data->power_on;
-
-       for (i = 0; i < num_domains; i++) {
-               const struct imx8mp_blk_ctrl_domain_data *data = &bc_data->domains[i];
-               struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
-               int j;
-
-               domain->data = data;
-               domain->num_paths = data->num_paths;
-
-               for (j = 0; j < data->num_clks; j++)
-                       domain->clks[j].id = data->clk_names[j];
-
-               for (j = 0; j < data->num_paths; j++) {
-                       domain->paths[j].name = data->path_names[j];
-                       /* Fake value for now, just let ICC could configure NoC mode/priority */
-                       domain->paths[j].avg_bw = 1;
-                       domain->paths[j].peak_bw = 1;
-               }
-
-               ret = devm_of_icc_bulk_get(dev, data->num_paths, domain->paths);
-               if (ret) {
-                       if (ret != -EPROBE_DEFER) {
-                               dev_warn_once(dev, "Could not get interconnect paths, NoC will stay unconfigured!\n");
-                               domain->num_paths = 0;
-                       } else {
-                               dev_err_probe(dev, ret, "failed to get noc entries\n");
-                               goto cleanup_pds;
-                       }
-               }
-
-               ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
-               if (ret) {
-                       dev_err_probe(dev, ret, "failed to get clock\n");
-                       goto cleanup_pds;
-               }
-
-               domain->power_dev =
-                       dev_pm_domain_attach_by_name(dev, data->gpc_name);
-               if (IS_ERR(domain->power_dev)) {
-                       dev_err_probe(dev, PTR_ERR(domain->power_dev),
-                                     "failed to attach power domain %s\n",
-                                     data->gpc_name);
-                       ret = PTR_ERR(domain->power_dev);
-                       goto cleanup_pds;
-               }
-
-               domain->genpd.name = data->name;
-               domain->genpd.power_on = imx8mp_blk_ctrl_power_on;
-               domain->genpd.power_off = imx8mp_blk_ctrl_power_off;
-               domain->bc = bc;
-               domain->id = i;
-
-               ret = pm_genpd_init(&domain->genpd, NULL, true);
-               if (ret) {
-                       dev_err_probe(dev, ret, "failed to init power domain\n");
-                       dev_pm_domain_detach(domain->power_dev, true);
-                       goto cleanup_pds;
-               }
-
-               /*
-                * We use runtime PM to trigger power on/off of the upstream GPC
-                * domain, as a strict hierarchical parent/child power domain
-                * setup doesn't allow us to meet the sequencing requirements.
-                * This means we have nested locking of genpd locks, without the
-                * nesting being visible at the genpd level, so we need a
-                * separate lock class to make lockdep aware of the fact that
-                * this are separate domain locks that can be nested without a
-                * self-deadlock.
-                */
-               lockdep_set_class(&domain->genpd.mlock,
-                                 &blk_ctrl_genpd_lock_class);
-
-               bc->onecell_data.domains[i] = &domain->genpd;
-       }
-
-       ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
-       if (ret) {
-               dev_err_probe(dev, ret, "failed to add power domain provider\n");
-               goto cleanup_pds;
-       }
-
-       bc->power_nb.notifier_call = bc_data->power_notifier_fn;
-       ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb);
-       if (ret) {
-               dev_err_probe(dev, ret, "failed to add power notifier\n");
-               goto cleanup_provider;
-       }
-
-       if (bc_data->probe) {
-               ret = bc_data->probe(bc);
-               if (ret)
-                       goto cleanup_provider;
-       }
-
-       dev_set_drvdata(dev, bc);
-
-       return 0;
-
-cleanup_provider:
-       of_genpd_del_provider(dev->of_node);
-cleanup_pds:
-       for (i--; i >= 0; i--) {
-               pm_genpd_remove(&bc->domains[i].genpd);
-               dev_pm_domain_detach(bc->domains[i].power_dev, true);
-       }
-
-       dev_pm_domain_detach(bc->bus_power_dev, true);
-
-       return ret;
-}
-
-static int imx8mp_blk_ctrl_remove(struct platform_device *pdev)
-{
-       struct imx8mp_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
-       int i;
-
-       of_genpd_del_provider(pdev->dev.of_node);
-
-       for (i = 0; bc->onecell_data.num_domains; i++) {
-               struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
-
-               pm_genpd_remove(&domain->genpd);
-               dev_pm_domain_detach(domain->power_dev, true);
-       }
-
-       dev_pm_genpd_remove_notifier(bc->bus_power_dev);
-
-       dev_pm_domain_detach(bc->bus_power_dev, true);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int imx8mp_blk_ctrl_suspend(struct device *dev)
-{
-       struct imx8mp_blk_ctrl *bc = dev_get_drvdata(dev);
-       int ret, i;
-
-       /*
-        * This may look strange, but is done so the generic PM_SLEEP code
-        * can power down our domains and more importantly power them up again
-        * after resume, without tripping over our usage of runtime PM to
-        * control the upstream GPC domains. Things happen in the right order
-        * in the system suspend/resume paths due to the device parent/child
-        * hierarchy.
-        */
-       ret = pm_runtime_get_sync(bc->bus_power_dev);
-       if (ret < 0) {
-               pm_runtime_put_noidle(bc->bus_power_dev);
-               return ret;
-       }
-
-       for (i = 0; i < bc->onecell_data.num_domains; i++) {
-               struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
-
-               ret = pm_runtime_get_sync(domain->power_dev);
-               if (ret < 0) {
-                       pm_runtime_put_noidle(domain->power_dev);
-                       goto out_fail;
-               }
-       }
-
-       return 0;
-
-out_fail:
-       for (i--; i >= 0; i--)
-               pm_runtime_put(bc->domains[i].power_dev);
-
-       pm_runtime_put(bc->bus_power_dev);
-
-       return ret;
-}
-
-static int imx8mp_blk_ctrl_resume(struct device *dev)
-{
-       struct imx8mp_blk_ctrl *bc = dev_get_drvdata(dev);
-       int i;
-
-       for (i = 0; i < bc->onecell_data.num_domains; i++)
-               pm_runtime_put(bc->domains[i].power_dev);
-
-       pm_runtime_put(bc->bus_power_dev);
-
-       return 0;
-}
-#endif
-
-static const struct dev_pm_ops imx8mp_blk_ctrl_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(imx8mp_blk_ctrl_suspend,
-                               imx8mp_blk_ctrl_resume)
-};
-
-static const struct of_device_id imx8mp_blk_ctrl_of_match[] = {
-       {
-               .compatible = "fsl,imx8mp-hsio-blk-ctrl",
-               .data = &imx8mp_hsio_blk_ctl_dev_data,
-       }, {
-               .compatible = "fsl,imx8mp-hdmi-blk-ctrl",
-               .data = &imx8mp_hdmi_blk_ctl_dev_data,
-       }, {
-               /* Sentinel */
-       }
-};
-MODULE_DEVICE_TABLE(of, imx8mp_blk_ctrl_of_match);
-
-static struct platform_driver imx8mp_blk_ctrl_driver = {
-       .probe = imx8mp_blk_ctrl_probe,
-       .remove = imx8mp_blk_ctrl_remove,
-       .driver = {
-               .name = "imx8mp-blk-ctrl",
-               .pm = &imx8mp_blk_ctrl_pm_ops,
-               .of_match_table = imx8mp_blk_ctrl_of_match,
-       },
-};
-module_platform_driver(imx8mp_blk_ctrl_driver);
-MODULE_LICENSE("GPL");
diff --git a/drivers/genpd/imx/imx93-blk-ctrl.c b/drivers/genpd/imx/imx93-blk-ctrl.c
deleted file mode 100644 (file)
index 40bd90f..0000000
+++ /dev/null
@@ -1,451 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright 2022 NXP, Peng Fan <peng.fan@nxp.com>
- */
-
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/pm_runtime.h>
-#include <linux/regmap.h>
-#include <linux/sizes.h>
-
-#include <dt-bindings/power/fsl,imx93-power.h>
-
-#define BLK_SFT_RSTN   0x0
-#define BLK_CLK_EN     0x4
-#define BLK_MAX_CLKS   4
-
-#define DOMAIN_MAX_CLKS 4
-
-#define LCDIF_QOS_REG          0xC
-#define LCDIF_DEFAULT_QOS_OFF  12
-#define LCDIF_CFG_QOS_OFF      8
-
-#define PXP_QOS_REG            0x10
-#define PXP_R_DEFAULT_QOS_OFF  28
-#define PXP_R_CFG_QOS_OFF      24
-#define PXP_W_DEFAULT_QOS_OFF  20
-#define PXP_W_CFG_QOS_OFF      16
-
-#define ISI_CACHE_REG          0x14
-
-#define ISI_QOS_REG            0x1C
-#define ISI_V_DEFAULT_QOS_OFF  28
-#define ISI_V_CFG_QOS_OFF      24
-#define ISI_U_DEFAULT_QOS_OFF  20
-#define ISI_U_CFG_QOS_OFF      16
-#define ISI_Y_R_DEFAULT_QOS_OFF        12
-#define ISI_Y_R_CFG_QOS_OFF    8
-#define ISI_Y_W_DEFAULT_QOS_OFF        4
-#define ISI_Y_W_CFG_QOS_OFF    0
-
-#define PRIO_MASK              0xF
-
-#define PRIO(X)                        (X)
-
-struct imx93_blk_ctrl_domain;
-
-struct imx93_blk_ctrl {
-       struct device *dev;
-       struct regmap *regmap;
-       int num_clks;
-       struct clk_bulk_data clks[BLK_MAX_CLKS];
-       struct imx93_blk_ctrl_domain *domains;
-       struct genpd_onecell_data onecell_data;
-};
-
-#define DOMAIN_MAX_QOS 4
-
-struct imx93_blk_ctrl_qos {
-       u32 reg;
-       u32 cfg_off;
-       u32 default_prio;
-       u32 cfg_prio;
-};
-
-struct imx93_blk_ctrl_domain_data {
-       const char *name;
-       const char * const *clk_names;
-       int num_clks;
-       u32 rst_mask;
-       u32 clk_mask;
-       int num_qos;
-       struct imx93_blk_ctrl_qos qos[DOMAIN_MAX_QOS];
-};
-
-struct imx93_blk_ctrl_domain {
-       struct generic_pm_domain genpd;
-       const struct imx93_blk_ctrl_domain_data *data;
-       struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
-       struct imx93_blk_ctrl *bc;
-};
-
-struct imx93_blk_ctrl_data {
-       const struct imx93_blk_ctrl_domain_data *domains;
-       int num_domains;
-       const char * const *clk_names;
-       int num_clks;
-       const struct regmap_access_table *reg_access_table;
-};
-
-static inline struct imx93_blk_ctrl_domain *
-to_imx93_blk_ctrl_domain(struct generic_pm_domain *genpd)
-{
-       return container_of(genpd, struct imx93_blk_ctrl_domain, genpd);
-}
-
-static int imx93_blk_ctrl_set_qos(struct imx93_blk_ctrl_domain *domain)
-{
-       const struct imx93_blk_ctrl_domain_data *data = domain->data;
-       struct imx93_blk_ctrl *bc = domain->bc;
-       const struct imx93_blk_ctrl_qos *qos;
-       u32 val, mask;
-       int i;
-
-       for (i = 0; i < data->num_qos; i++) {
-               qos = &data->qos[i];
-
-               mask = PRIO_MASK << qos->cfg_off;
-               mask |= PRIO_MASK << (qos->cfg_off + 4);
-               val = qos->cfg_prio << qos->cfg_off;
-               val |= qos->default_prio << (qos->cfg_off + 4);
-
-               regmap_write_bits(bc->regmap, qos->reg, mask, val);
-
-               dev_dbg(bc->dev, "data->qos[i].reg 0x%x 0x%x\n", qos->reg, val);
-       }
-
-       return 0;
-}
-
-static int imx93_blk_ctrl_power_on(struct generic_pm_domain *genpd)
-{
-       struct imx93_blk_ctrl_domain *domain = to_imx93_blk_ctrl_domain(genpd);
-       const struct imx93_blk_ctrl_domain_data *data = domain->data;
-       struct imx93_blk_ctrl *bc = domain->bc;
-       int ret;
-
-       ret = clk_bulk_prepare_enable(bc->num_clks, bc->clks);
-       if (ret) {
-               dev_err(bc->dev, "failed to enable bus clocks\n");
-               return ret;
-       }
-
-       ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
-       if (ret) {
-               clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
-               dev_err(bc->dev, "failed to enable clocks\n");
-               return ret;
-       }
-
-       ret = pm_runtime_get_sync(bc->dev);
-       if (ret < 0) {
-               pm_runtime_put_noidle(bc->dev);
-               dev_err(bc->dev, "failed to power up domain\n");
-               goto disable_clk;
-       }
-
-       /* ungate clk */
-       regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
-
-       /* release reset */
-       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
-
-       dev_dbg(bc->dev, "pd_on: name: %s\n", genpd->name);
-
-       return imx93_blk_ctrl_set_qos(domain);
-
-disable_clk:
-       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
-
-       clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
-
-       return ret;
-}
-
-static int imx93_blk_ctrl_power_off(struct generic_pm_domain *genpd)
-{
-       struct imx93_blk_ctrl_domain *domain = to_imx93_blk_ctrl_domain(genpd);
-       const struct imx93_blk_ctrl_domain_data *data = domain->data;
-       struct imx93_blk_ctrl *bc = domain->bc;
-
-       dev_dbg(bc->dev, "pd_off: name: %s\n", genpd->name);
-
-       regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
-       regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
-
-       pm_runtime_put(bc->dev);
-
-       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
-
-       clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
-
-       return 0;
-}
-
-static struct lock_class_key blk_ctrl_genpd_lock_class;
-
-static int imx93_blk_ctrl_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       const struct imx93_blk_ctrl_data *bc_data = of_device_get_match_data(dev);
-       struct imx93_blk_ctrl *bc;
-       void __iomem *base;
-       int i, ret;
-
-       struct regmap_config regmap_config = {
-               .reg_bits       = 32,
-               .val_bits       = 32,
-               .reg_stride     = 4,
-               .rd_table       = bc_data->reg_access_table,
-               .wr_table       = bc_data->reg_access_table,
-               .max_register   = SZ_4K,
-       };
-
-       bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
-       if (!bc)
-               return -ENOMEM;
-
-       bc->dev = dev;
-
-       base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
-       if (IS_ERR(bc->regmap))
-               return dev_err_probe(dev, PTR_ERR(bc->regmap),
-                                    "failed to init regmap\n");
-
-       bc->domains = devm_kcalloc(dev, bc_data->num_domains,
-                                  sizeof(struct imx93_blk_ctrl_domain),
-                                  GFP_KERNEL);
-       if (!bc->domains)
-               return -ENOMEM;
-
-       bc->onecell_data.num_domains = bc_data->num_domains;
-       bc->onecell_data.domains =
-               devm_kcalloc(dev, bc_data->num_domains,
-                            sizeof(struct generic_pm_domain *), GFP_KERNEL);
-       if (!bc->onecell_data.domains)
-               return -ENOMEM;
-
-       for (i = 0; i < bc_data->num_clks; i++)
-               bc->clks[i].id = bc_data->clk_names[i];
-       bc->num_clks = bc_data->num_clks;
-
-       ret = devm_clk_bulk_get(dev, bc->num_clks, bc->clks);
-       if (ret) {
-               dev_err_probe(dev, ret, "failed to get bus clock\n");
-               return ret;
-       }
-
-       for (i = 0; i < bc_data->num_domains; i++) {
-               const struct imx93_blk_ctrl_domain_data *data = &bc_data->domains[i];
-               struct imx93_blk_ctrl_domain *domain = &bc->domains[i];
-               int j;
-
-               domain->data = data;
-
-               for (j = 0; j < data->num_clks; j++)
-                       domain->clks[j].id = data->clk_names[j];
-
-               ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
-               if (ret) {
-                       dev_err_probe(dev, ret, "failed to get clock\n");
-                       goto cleanup_pds;
-               }
-
-               domain->genpd.name = data->name;
-               domain->genpd.power_on = imx93_blk_ctrl_power_on;
-               domain->genpd.power_off = imx93_blk_ctrl_power_off;
-               domain->bc = bc;
-
-               ret = pm_genpd_init(&domain->genpd, NULL, true);
-               if (ret) {
-                       dev_err_probe(dev, ret, "failed to init power domain\n");
-                       goto cleanup_pds;
-               }
-
-               /*
-                * We use runtime PM to trigger power on/off of the upstream GPC
-                * domain, as a strict hierarchical parent/child power domain
-                * setup doesn't allow us to meet the sequencing requirements.
-                * This means we have nested locking of genpd locks, without the
-                * nesting being visible at the genpd level, so we need a
-                * separate lock class to make lockdep aware of the fact that
-                * this are separate domain locks that can be nested without a
-                * self-deadlock.
-                */
-               lockdep_set_class(&domain->genpd.mlock,
-                                 &blk_ctrl_genpd_lock_class);
-
-               bc->onecell_data.domains[i] = &domain->genpd;
-       }
-
-       pm_runtime_enable(dev);
-
-       ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
-       if (ret) {
-               dev_err_probe(dev, ret, "failed to add power domain provider\n");
-               goto cleanup_pds;
-       }
-
-       dev_set_drvdata(dev, bc);
-
-       return 0;
-
-cleanup_pds:
-       for (i--; i >= 0; i--)
-               pm_genpd_remove(&bc->domains[i].genpd);
-
-       return ret;
-}
-
-static int imx93_blk_ctrl_remove(struct platform_device *pdev)
-{
-       struct imx93_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
-       int i;
-
-       of_genpd_del_provider(pdev->dev.of_node);
-
-       for (i = 0; bc->onecell_data.num_domains; i++) {
-               struct imx93_blk_ctrl_domain *domain = &bc->domains[i];
-
-               pm_genpd_remove(&domain->genpd);
-       }
-
-       return 0;
-}
-
-static const struct imx93_blk_ctrl_domain_data imx93_media_blk_ctl_domain_data[] = {
-       [IMX93_MEDIABLK_PD_MIPI_DSI] = {
-               .name = "mediablk-mipi-dsi",
-               .clk_names = (const char *[]){ "dsi" },
-               .num_clks = 1,
-               .rst_mask = BIT(11) | BIT(12),
-               .clk_mask = BIT(11) | BIT(12),
-       },
-       [IMX93_MEDIABLK_PD_MIPI_CSI] = {
-               .name = "mediablk-mipi-csi",
-               .clk_names = (const char *[]){ "cam", "csi" },
-               .num_clks = 2,
-               .rst_mask = BIT(9) | BIT(10),
-               .clk_mask = BIT(9) | BIT(10),
-       },
-       [IMX93_MEDIABLK_PD_PXP] = {
-               .name = "mediablk-pxp",
-               .clk_names = (const char *[]){ "pxp" },
-               .num_clks = 1,
-               .rst_mask = BIT(7) | BIT(8),
-               .clk_mask = BIT(7) | BIT(8),
-               .num_qos = 2,
-               .qos = {
-                       {
-                               .reg = PXP_QOS_REG,
-                               .cfg_off = PXP_R_CFG_QOS_OFF,
-                               .default_prio = PRIO(3),
-                               .cfg_prio = PRIO(6),
-                       }, {
-                               .reg = PXP_QOS_REG,
-                               .cfg_off = PXP_W_CFG_QOS_OFF,
-                               .default_prio = PRIO(3),
-                               .cfg_prio = PRIO(6),
-                       }
-               }
-       },
-       [IMX93_MEDIABLK_PD_LCDIF] = {
-               .name = "mediablk-lcdif",
-               .clk_names = (const char *[]){ "disp", "lcdif" },
-               .num_clks = 2,
-               .rst_mask = BIT(4) | BIT(5) | BIT(6),
-               .clk_mask = BIT(4) | BIT(5) | BIT(6),
-               .num_qos = 1,
-               .qos = {
-                       {
-                       .reg = LCDIF_QOS_REG,
-                       .cfg_off = LCDIF_CFG_QOS_OFF,
-                       .default_prio = PRIO(3),
-                       .cfg_prio = PRIO(7),
-                       }
-               }
-       },
-       [IMX93_MEDIABLK_PD_ISI] = {
-               .name = "mediablk-isi",
-               .clk_names = (const char *[]){ "isi" },
-               .num_clks = 1,
-               .rst_mask = BIT(2) | BIT(3),
-               .clk_mask = BIT(2) | BIT(3),
-               .num_qos = 4,
-               .qos = {
-                       {
-                               .reg = ISI_QOS_REG,
-                               .cfg_off = ISI_Y_W_CFG_QOS_OFF,
-                               .default_prio = PRIO(3),
-                               .cfg_prio = PRIO(7),
-                       }, {
-                               .reg = ISI_QOS_REG,
-                               .cfg_off = ISI_Y_R_CFG_QOS_OFF,
-                               .default_prio = PRIO(3),
-                               .cfg_prio = PRIO(7),
-                       }, {
-                               .reg = ISI_QOS_REG,
-                               .cfg_off = ISI_U_CFG_QOS_OFF,
-                               .default_prio = PRIO(3),
-                               .cfg_prio = PRIO(7),
-                       }, {
-                               .reg = ISI_QOS_REG,
-                               .cfg_off = ISI_V_CFG_QOS_OFF,
-                               .default_prio = PRIO(3),
-                               .cfg_prio = PRIO(7),
-                       }
-               }
-       },
-};
-
-static const struct regmap_range imx93_media_blk_ctl_yes_ranges[] = {
-       regmap_reg_range(BLK_SFT_RSTN, BLK_CLK_EN),
-       regmap_reg_range(LCDIF_QOS_REG, ISI_CACHE_REG),
-       regmap_reg_range(ISI_QOS_REG, ISI_QOS_REG),
-};
-
-static const struct regmap_access_table imx93_media_blk_ctl_access_table = {
-       .yes_ranges = imx93_media_blk_ctl_yes_ranges,
-       .n_yes_ranges = ARRAY_SIZE(imx93_media_blk_ctl_yes_ranges),
-};
-
-static const struct imx93_blk_ctrl_data imx93_media_blk_ctl_dev_data = {
-       .domains = imx93_media_blk_ctl_domain_data,
-       .num_domains = ARRAY_SIZE(imx93_media_blk_ctl_domain_data),
-       .clk_names = (const char *[]){ "axi", "apb", "nic", },
-       .num_clks = 3,
-       .reg_access_table = &imx93_media_blk_ctl_access_table,
-};
-
-static const struct of_device_id imx93_blk_ctrl_of_match[] = {
-       {
-               .compatible = "fsl,imx93-media-blk-ctrl",
-               .data = &imx93_media_blk_ctl_dev_data
-       }, {
-               /* Sentinel */
-       }
-};
-MODULE_DEVICE_TABLE(of, imx93_blk_ctrl_of_match);
-
-static struct platform_driver imx93_blk_ctrl_driver = {
-       .probe = imx93_blk_ctrl_probe,
-       .remove = imx93_blk_ctrl_remove,
-       .driver = {
-               .name = "imx93-blk-ctrl",
-               .of_match_table = imx93_blk_ctrl_of_match,
-       },
-};
-module_platform_driver(imx93_blk_ctrl_driver);
-
-MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
-MODULE_DESCRIPTION("i.MX93 BLK CTRL driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/genpd/imx/imx93-pd.c b/drivers/genpd/imx/imx93-pd.c
deleted file mode 100644 (file)
index b9e60d1..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright 2022 NXP
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/iopoll.h>
-#include <linux/mod_devicetable.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-
-#define MIX_SLICE_SW_CTRL_OFF          0x20
-#define SLICE_SW_CTRL_PSW_CTRL_OFF_MASK        BIT(4)
-#define SLICE_SW_CTRL_PDN_SOFT_MASK    BIT(31)
-
-#define MIX_FUNC_STAT_OFF              0xB4
-
-#define FUNC_STAT_PSW_STAT_MASK                BIT(0)
-#define FUNC_STAT_RST_STAT_MASK                BIT(2)
-#define FUNC_STAT_ISO_STAT_MASK                BIT(4)
-
-struct imx93_power_domain {
-       struct generic_pm_domain genpd;
-       struct device *dev;
-       void __iomem *addr;
-       struct clk_bulk_data *clks;
-       int num_clks;
-       bool init_off;
-};
-
-#define to_imx93_pd(_genpd) container_of(_genpd, struct imx93_power_domain, genpd)
-
-static int imx93_pd_on(struct generic_pm_domain *genpd)
-{
-       struct imx93_power_domain *domain = to_imx93_pd(genpd);
-       void __iomem *addr = domain->addr;
-       u32 val;
-       int ret;
-
-       ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
-       if (ret) {
-               dev_err(domain->dev, "failed to enable clocks for domain: %s\n", genpd->name);
-               return ret;
-       }
-
-       val = readl(addr + MIX_SLICE_SW_CTRL_OFF);
-       val &= ~SLICE_SW_CTRL_PDN_SOFT_MASK;
-       writel(val, addr + MIX_SLICE_SW_CTRL_OFF);
-
-       ret = readl_poll_timeout(addr + MIX_FUNC_STAT_OFF, val,
-                                !(val & FUNC_STAT_ISO_STAT_MASK), 1, 10000);
-       if (ret) {
-               dev_err(domain->dev, "pd_on timeout: name: %s, stat: %x\n", genpd->name, val);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int imx93_pd_off(struct generic_pm_domain *genpd)
-{
-       struct imx93_power_domain *domain = to_imx93_pd(genpd);
-       void __iomem *addr = domain->addr;
-       int ret;
-       u32 val;
-
-       /* Power off MIX */
-       val = readl(addr + MIX_SLICE_SW_CTRL_OFF);
-       val |= SLICE_SW_CTRL_PDN_SOFT_MASK;
-       writel(val, addr + MIX_SLICE_SW_CTRL_OFF);
-
-       ret = readl_poll_timeout(addr + MIX_FUNC_STAT_OFF, val,
-                                val & FUNC_STAT_PSW_STAT_MASK, 1, 1000);
-       if (ret) {
-               dev_err(domain->dev, "pd_off timeout: name: %s, stat: %x\n", genpd->name, val);
-               return ret;
-       }
-
-       clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
-
-       return 0;
-};
-
-static int imx93_pd_remove(struct platform_device *pdev)
-{
-       struct imx93_power_domain *domain = platform_get_drvdata(pdev);
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-
-       if (!domain->init_off)
-               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
-
-       of_genpd_del_provider(np);
-       pm_genpd_remove(&domain->genpd);
-
-       return 0;
-}
-
-static int imx93_pd_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       struct imx93_power_domain *domain;
-       int ret;
-
-       domain = devm_kzalloc(dev, sizeof(*domain), GFP_KERNEL);
-       if (!domain)
-               return -ENOMEM;
-
-       domain->addr = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(domain->addr))
-               return PTR_ERR(domain->addr);
-
-       domain->num_clks = devm_clk_bulk_get_all(dev, &domain->clks);
-       if (domain->num_clks < 0)
-               return dev_err_probe(dev, domain->num_clks, "Failed to get domain's clocks\n");
-
-       domain->genpd.name = dev_name(dev);
-       domain->genpd.power_off = imx93_pd_off;
-       domain->genpd.power_on = imx93_pd_on;
-       domain->dev = dev;
-
-       domain->init_off = readl(domain->addr + MIX_FUNC_STAT_OFF) & FUNC_STAT_ISO_STAT_MASK;
-       /* Just to sync the status of hardware */
-       if (!domain->init_off) {
-               ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
-               if (ret) {
-                       dev_err(domain->dev, "failed to enable clocks for domain: %s\n",
-                               domain->genpd.name);
-                       return ret;
-               }
-       }
-
-       ret = pm_genpd_init(&domain->genpd, NULL, domain->init_off);
-       if (ret)
-               goto err_clk_unprepare;
-
-       platform_set_drvdata(pdev, domain);
-
-       ret = of_genpd_add_provider_simple(np, &domain->genpd);
-       if (ret)
-               goto err_genpd_remove;
-
-       return 0;
-
-err_genpd_remove:
-       pm_genpd_remove(&domain->genpd);
-
-err_clk_unprepare:
-       if (!domain->init_off)
-               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
-
-       return ret;
-}
-
-static const struct of_device_id imx93_pd_ids[] = {
-       { .compatible = "fsl,imx93-src-slice" },
-       { }
-};
-MODULE_DEVICE_TABLE(of, imx93_pd_ids);
-
-static struct platform_driver imx93_power_domain_driver = {
-       .driver = {
-               .name   = "imx93_power_domain",
-               .of_match_table = imx93_pd_ids,
-       },
-       .probe = imx93_pd_probe,
-       .remove = imx93_pd_remove,
-};
-module_platform_driver(imx93_power_domain_driver);
-
-MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
-MODULE_DESCRIPTION("NXP i.MX93 power domain driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/genpd/imx/scu-pd.c b/drivers/genpd/imx/scu-pd.c
deleted file mode 100644 (file)
index 2f693b6..0000000
+++ /dev/null
@@ -1,550 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2016 Freescale Semiconductor, Inc.
- * Copyright 2017-2018 NXP
- *     Dong Aisheng <aisheng.dong@nxp.com>
- *
- * Implementation of the SCU based Power Domains
- *
- * NOTE: a better implementation suggested by Ulf Hansson is using a
- * single global power domain and implement the ->attach|detach_dev()
- * callback for the genpd and use the regular of_genpd_add_provider_simple().
- * From within the ->attach_dev(), we could get the OF node for
- * the device that is being attached and then parse the power-domain
- * cell containing the "resource id" and store that in the per device
- * struct generic_pm_domain_data (we have void pointer there for
- * storing these kind of things).
- *
- * Additionally, we need to implement the ->stop() and ->start()
- * callbacks of genpd, which is where you "power on/off" devices,
- * rather than using the above ->power_on|off() callbacks.
- *
- * However, there're two known issues:
- * 1. The ->attach_dev() of power domain infrastructure still does
- *    not support multi domains case as the struct device *dev passed
- *    in is a virtual PD device, it does not help for parsing the real
- *    device resource id from device tree, so it's unware of which
- *    real sub power domain of device should be attached.
- *
- *    The framework needs some proper extension to support multi power
- *    domain cases.
- *
- *    Update: Genpd assigns the ->of_node for the virtual device before it
- *    invokes ->attach_dev() callback, hence parsing for device resources via
- *    DT should work fine.
- *
- * 2. It also breaks most of current drivers as the driver probe sequence
- *    behavior changed if removing ->power_on|off() callback and use
- *    ->start() and ->stop() instead. genpd_dev_pm_attach will only power
- *    up the domain and attach device, but will not call .start() which
- *    relies on device runtime pm. That means the device power is still
- *    not up before running driver probe function. For SCU enabled
- *    platforms, all device drivers accessing registers/clock without power
- *    domain enabled will trigger a HW access error. That means we need fix
- *    most drivers probe sequence with proper runtime pm.
- *
- *    Update: Runtime PM support isn't necessary. Instead, this can easily be
- *    fixed in drivers by adding a call to dev_pm_domain_start() during probe.
- *
- * In summary, the second part needs to be addressed via minor updates to the
- * relevant drivers, before the "single global power domain" model can be used.
- *
- */
-
-#include <dt-bindings/firmware/imx/rsrc.h>
-#include <linux/console.h>
-#include <linux/firmware/imx/sci.h>
-#include <linux/firmware/imx/svc/rm.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/pm.h>
-#include <linux/pm_domain.h>
-#include <linux/slab.h>
-
-/* SCU Power Mode Protocol definition */
-struct imx_sc_msg_req_set_resource_power_mode {
-       struct imx_sc_rpc_msg hdr;
-       u16 resource;
-       u8 mode;
-} __packed __aligned(4);
-
-struct req_get_resource_mode {
-       u16 resource;
-};
-
-struct resp_get_resource_mode {
-       u8 mode;
-};
-
-struct imx_sc_msg_req_get_resource_power_mode {
-       struct imx_sc_rpc_msg hdr;
-       union {
-               struct req_get_resource_mode req;
-               struct resp_get_resource_mode resp;
-       } data;
-} __packed __aligned(4);
-
-#define IMX_SCU_PD_NAME_SIZE 20
-struct imx_sc_pm_domain {
-       struct generic_pm_domain pd;
-       char name[IMX_SCU_PD_NAME_SIZE];
-       u32 rsrc;
-};
-
-struct imx_sc_pd_range {
-       char *name;
-       u32 rsrc;
-       u8 num;
-
-       /* add domain index */
-       bool postfix;
-       u8 start_from;
-};
-
-struct imx_sc_pd_soc {
-       const struct imx_sc_pd_range *pd_ranges;
-       u8 num_ranges;
-};
-
-static int imx_con_rsrc;
-
-/* Align with the IMX_SC_PM_PW_MODE_[OFF,STBY,LP,ON] macros */
-static const char * const imx_sc_pm_mode[] = {
-       "IMX_SC_PM_PW_MODE_OFF",
-       "IMX_SC_PM_PW_MODE_STBY",
-       "IMX_SC_PM_PW_MODE_LP",
-       "IMX_SC_PM_PW_MODE_ON"
-};
-
-static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
-       /* LSIO SS */
-       { "pwm", IMX_SC_R_PWM_0, 8, true, 0 },
-       { "gpio", IMX_SC_R_GPIO_0, 8, true, 0 },
-       { "gpt", IMX_SC_R_GPT_0, 5, true, 0 },
-       { "kpp", IMX_SC_R_KPP, 1, false, 0 },
-       { "fspi", IMX_SC_R_FSPI_0, 2, true, 0 },
-       { "mu_a", IMX_SC_R_MU_0A, 14, true, 0 },
-       { "mu_b", IMX_SC_R_MU_5B, 9, true, 5 },
-
-       /* CONN SS */
-       { "usb", IMX_SC_R_USB_0, 2, true, 0 },
-       { "usb0phy", IMX_SC_R_USB_0_PHY, 1, false, 0 },
-       { "usb1phy", IMX_SC_R_USB_1_PHY, 1, false, 0},
-       { "usb2", IMX_SC_R_USB_2, 1, false, 0 },
-       { "usb2phy", IMX_SC_R_USB_2_PHY, 1, false, 0 },
-       { "sdhc", IMX_SC_R_SDHC_0, 3, true, 0 },
-       { "enet", IMX_SC_R_ENET_0, 2, true, 0 },
-       { "nand", IMX_SC_R_NAND, 1, false, 0 },
-       { "mlb", IMX_SC_R_MLB_0, 1, true, 0 },
-
-       /* AUDIO SS */
-       { "audio-pll0", IMX_SC_R_AUDIO_PLL_0, 1, false, 0 },
-       { "audio-pll1", IMX_SC_R_AUDIO_PLL_1, 1, false, 0 },
-       { "audio-clk-0", IMX_SC_R_AUDIO_CLK_0, 1, false, 0 },
-       { "audio-clk-1", IMX_SC_R_AUDIO_CLK_1, 1, false, 0 },
-       { "mclk-out-0", IMX_SC_R_MCLK_OUT_0, 1, false, 0 },
-       { "mclk-out-1", IMX_SC_R_MCLK_OUT_1, 1, false, 0 },
-       { "dma0-ch", IMX_SC_R_DMA_0_CH0, 32, true, 0 },
-       { "dma1-ch", IMX_SC_R_DMA_1_CH0, 16, true, 0 },
-       { "dma2-ch", IMX_SC_R_DMA_2_CH0, 32, true, 0 },
-       { "dma3-ch", IMX_SC_R_DMA_3_CH0, 32, true, 0 },
-       { "asrc0", IMX_SC_R_ASRC_0, 1, false, 0 },
-       { "asrc1", IMX_SC_R_ASRC_1, 1, false, 0 },
-       { "esai0", IMX_SC_R_ESAI_0, 1, false, 0 },
-       { "esai1", IMX_SC_R_ESAI_1, 1, false, 0 },
-       { "spdif0", IMX_SC_R_SPDIF_0, 1, false, 0 },
-       { "spdif1", IMX_SC_R_SPDIF_1, 1, false, 0 },
-       { "sai", IMX_SC_R_SAI_0, 3, true, 0 },
-       { "sai3", IMX_SC_R_SAI_3, 1, false, 0 },
-       { "sai4", IMX_SC_R_SAI_4, 1, false, 0 },
-       { "sai5", IMX_SC_R_SAI_5, 1, false, 0 },
-       { "sai6", IMX_SC_R_SAI_6, 1, false, 0 },
-       { "sai7", IMX_SC_R_SAI_7, 1, false, 0 },
-       { "amix", IMX_SC_R_AMIX, 1, false, 0 },
-       { "mqs0", IMX_SC_R_MQS_0, 1, false, 0 },
-       { "dsp", IMX_SC_R_DSP, 1, false, 0 },
-       { "dsp-ram", IMX_SC_R_DSP_RAM, 1, false, 0 },
-
-       /* DMA SS */
-       { "can", IMX_SC_R_CAN_0, 3, true, 0 },
-       { "ftm", IMX_SC_R_FTM_0, 2, true, 0 },
-       { "lpi2c", IMX_SC_R_I2C_0, 5, true, 0 },
-       { "adc", IMX_SC_R_ADC_0, 2, true, 0 },
-       { "lcd", IMX_SC_R_LCD_0, 1, true, 0 },
-       { "lcd-pll", IMX_SC_R_ELCDIF_PLL, 1, true, 0 },
-       { "lcd0-pwm", IMX_SC_R_LCD_0_PWM_0, 1, true, 0 },
-       { "lpuart", IMX_SC_R_UART_0, 5, true, 0 },
-       { "sim", IMX_SC_R_EMVSIM_0, 2, true, 0 },
-       { "lpspi", IMX_SC_R_SPI_0, 4, true, 0 },
-       { "irqstr_dsp", IMX_SC_R_IRQSTR_DSP, 1, false, 0 },
-
-       /* VPU SS */
-       { "vpu", IMX_SC_R_VPU, 1, false, 0 },
-       { "vpu-pid", IMX_SC_R_VPU_PID0, 8, true, 0 },
-       { "vpu-dec0", IMX_SC_R_VPU_DEC_0, 1, false, 0 },
-       { "vpu-enc0", IMX_SC_R_VPU_ENC_0, 1, false, 0 },
-       { "vpu-enc1", IMX_SC_R_VPU_ENC_1, 1, false, 0 },
-       { "vpu-mu0", IMX_SC_R_VPU_MU_0, 1, false, 0 },
-       { "vpu-mu1", IMX_SC_R_VPU_MU_1, 1, false, 0 },
-       { "vpu-mu2", IMX_SC_R_VPU_MU_2, 1, false, 0 },
-
-       /* GPU SS */
-       { "gpu0-pid", IMX_SC_R_GPU_0_PID0, 4, true, 0 },
-       { "gpu1-pid", IMX_SC_R_GPU_1_PID0, 4, true, 0 },
-
-
-       /* HSIO SS */
-       { "pcie-a", IMX_SC_R_PCIE_A, 1, false, 0 },
-       { "serdes-0", IMX_SC_R_SERDES_0, 1, false, 0 },
-       { "pcie-b", IMX_SC_R_PCIE_B, 1, false, 0 },
-       { "serdes-1", IMX_SC_R_SERDES_1, 1, false, 0 },
-       { "sata-0", IMX_SC_R_SATA_0, 1, false, 0 },
-       { "hsio-gpio", IMX_SC_R_HSIO_GPIO, 1, false, 0 },
-
-       /* MIPI SS */
-       { "mipi0", IMX_SC_R_MIPI_0, 1, false, 0 },
-       { "mipi0-pwm0", IMX_SC_R_MIPI_0_PWM_0, 1, false, 0 },
-       { "mipi0-i2c", IMX_SC_R_MIPI_0_I2C_0, 2, true, 0 },
-
-       { "mipi1", IMX_SC_R_MIPI_1, 1, false, 0 },
-       { "mipi1-pwm0", IMX_SC_R_MIPI_1_PWM_0, 1, false, 0 },
-       { "mipi1-i2c", IMX_SC_R_MIPI_1_I2C_0, 2, true, 0 },
-
-       /* LVDS SS */
-       { "lvds0", IMX_SC_R_LVDS_0, 1, false, 0 },
-       { "lvds0-pwm", IMX_SC_R_LVDS_0_PWM_0, 1, false, 0 },
-       { "lvds0-lpi2c", IMX_SC_R_LVDS_0_I2C_0, 2, true, 0 },
-       { "lvds1", IMX_SC_R_LVDS_1, 1, false, 0 },
-       { "lvds1-pwm", IMX_SC_R_LVDS_1_PWM_0, 1, false, 0 },
-       { "lvds1-lpi2c", IMX_SC_R_LVDS_1_I2C_0, 2, true, 0 },
-
-       { "mipi1", IMX_SC_R_MIPI_1, 1, 0 },
-       { "mipi1-pwm0", IMX_SC_R_MIPI_1_PWM_0, 1, 0 },
-       { "mipi1-i2c", IMX_SC_R_MIPI_1_I2C_0, 2, 1 },
-       { "lvds1", IMX_SC_R_LVDS_1, 1, 0 },
-
-       /* DC SS */
-       { "dc0", IMX_SC_R_DC_0, 1, false, 0 },
-       { "dc0-pll", IMX_SC_R_DC_0_PLL_0, 2, true, 0 },
-       { "dc0-video", IMX_SC_R_DC_0_VIDEO0, 2, true, 0 },
-
-       { "dc1", IMX_SC_R_DC_1, 1, false, 0 },
-       { "dc1-pll", IMX_SC_R_DC_1_PLL_0, 2, true, 0 },
-       { "dc1-video", IMX_SC_R_DC_1_VIDEO0, 2, true, 0 },
-
-       /* CM40 SS */
-       { "cm40-i2c", IMX_SC_R_M4_0_I2C, 1, false, 0 },
-       { "cm40-intmux", IMX_SC_R_M4_0_INTMUX, 1, false, 0 },
-       { "cm40-pid", IMX_SC_R_M4_0_PID0, 5, true, 0},
-       { "cm40-mu-a1", IMX_SC_R_M4_0_MU_1A, 1, false, 0},
-       { "cm40-lpuart", IMX_SC_R_M4_0_UART, 1, false, 0},
-
-       /* CM41 SS */
-       { "cm41-i2c", IMX_SC_R_M4_1_I2C, 1, false, 0 },
-       { "cm41-intmux", IMX_SC_R_M4_1_INTMUX, 1, false, 0 },
-       { "cm41-pid", IMX_SC_R_M4_1_PID0, 5, true, 0},
-       { "cm41-mu-a1", IMX_SC_R_M4_1_MU_1A, 1, false, 0},
-       { "cm41-lpuart", IMX_SC_R_M4_1_UART, 1, false, 0},
-
-       /* CM41 SS */
-       { "cm41_i2c", IMX_SC_R_M4_1_I2C, 1, false, 0 },
-       { "cm41_intmux", IMX_SC_R_M4_1_INTMUX, 1, false, 0 },
-
-       /* DB SS */
-       { "perf", IMX_SC_R_PERF, 1, false, 0},
-
-       /* IMAGE SS */
-       { "img-jpegdec-mp", IMX_SC_R_MJPEG_DEC_MP, 1, false, 0 },
-       { "img-jpegdec-s0", IMX_SC_R_MJPEG_DEC_S0, 4, true, 0 },
-       { "img-jpegenc-mp", IMX_SC_R_MJPEG_ENC_MP, 1, false, 0 },
-       { "img-jpegenc-s0", IMX_SC_R_MJPEG_ENC_S0, 4, true, 0 },
-
-       /* SECO SS */
-       { "seco_mu", IMX_SC_R_SECO_MU_2, 3, true, 2},
-
-       /* V2X SS */
-       { "v2x_mu", IMX_SC_R_V2X_MU_0, 2, true, 0},
-       { "v2x_mu", IMX_SC_R_V2X_MU_2, 1, true, 2},
-       { "v2x_mu", IMX_SC_R_V2X_MU_3, 2, true, 3},
-       { "img-pdma", IMX_SC_R_ISI_CH0, 8, true, 0 },
-       { "img-csi0", IMX_SC_R_CSI_0, 1, false, 0 },
-       { "img-csi0-i2c0", IMX_SC_R_CSI_0_I2C_0, 1, false, 0 },
-       { "img-csi0-pwm0", IMX_SC_R_CSI_0_PWM_0, 1, false, 0 },
-       { "img-csi1", IMX_SC_R_CSI_1, 1, false, 0 },
-       { "img-csi1-i2c0", IMX_SC_R_CSI_1_I2C_0, 1, false, 0 },
-       { "img-csi1-pwm0", IMX_SC_R_CSI_1_PWM_0, 1, false, 0 },
-       { "img-parallel", IMX_SC_R_PI_0, 1, false, 0 },
-       { "img-parallel-i2c0", IMX_SC_R_PI_0_I2C_0, 1, false, 0 },
-       { "img-parallel-pwm0", IMX_SC_R_PI_0_PWM_0, 2, true, 0 },
-       { "img-parallel-pll", IMX_SC_R_PI_0_PLL, 1, false, 0 },
-
-       /* HDMI TX SS */
-       { "hdmi-tx", IMX_SC_R_HDMI, 1, false, 0},
-       { "hdmi-tx-i2s", IMX_SC_R_HDMI_I2S, 1, false, 0},
-       { "hdmi-tx-i2c0", IMX_SC_R_HDMI_I2C_0, 1, false, 0},
-       { "hdmi-tx-pll0", IMX_SC_R_HDMI_PLL_0, 1, false, 0},
-       { "hdmi-tx-pll1", IMX_SC_R_HDMI_PLL_1, 1, false, 0},
-
-       /* HDMI RX SS */
-       { "hdmi-rx", IMX_SC_R_HDMI_RX, 1, false, 0},
-       { "hdmi-rx-pwm", IMX_SC_R_HDMI_RX_PWM_0, 1, false, 0},
-       { "hdmi-rx-i2c0", IMX_SC_R_HDMI_RX_I2C_0, 1, false, 0},
-       { "hdmi-rx-bypass", IMX_SC_R_HDMI_RX_BYPASS, 1, false, 0},
-
-       /* SECURITY SS */
-       { "sec-jr", IMX_SC_R_CAAM_JR2, 2, true, 2},
-
-       /* BOARD SS */
-       { "board", IMX_SC_R_BOARD_R0, 8, true, 0},
-};
-
-static const struct imx_sc_pd_soc imx8qxp_scu_pd = {
-       .pd_ranges = imx8qxp_scu_pd_ranges,
-       .num_ranges = ARRAY_SIZE(imx8qxp_scu_pd_ranges),
-};
-
-static struct imx_sc_ipc *pm_ipc_handle;
-
-static inline struct imx_sc_pm_domain *
-to_imx_sc_pd(struct generic_pm_domain *genpd)
-{
-       return container_of(genpd, struct imx_sc_pm_domain, pd);
-}
-
-static void imx_sc_pd_get_console_rsrc(void)
-{
-       struct of_phandle_args specs;
-       int ret;
-
-       if (!of_stdout)
-               return;
-
-       ret = of_parse_phandle_with_args(of_stdout, "power-domains",
-                                        "#power-domain-cells",
-                                        0, &specs);
-       if (ret)
-               return;
-
-       imx_con_rsrc = specs.args[0];
-}
-
-static int imx_sc_get_pd_power(struct device *dev, u32 rsrc)
-{
-       struct imx_sc_msg_req_get_resource_power_mode msg;
-       struct imx_sc_rpc_msg *hdr = &msg.hdr;
-       int ret;
-
-       hdr->ver = IMX_SC_RPC_VERSION;
-       hdr->svc = IMX_SC_RPC_SVC_PM;
-       hdr->func = IMX_SC_PM_FUNC_GET_RESOURCE_POWER_MODE;
-       hdr->size = 2;
-
-       msg.data.req.resource = rsrc;
-
-       ret = imx_scu_call_rpc(pm_ipc_handle, &msg, true);
-       if (ret)
-               dev_err(dev, "failed to get power resource %d mode, ret %d\n",
-                       rsrc, ret);
-
-       return msg.data.resp.mode;
-}
-
-static int imx_sc_pd_power(struct generic_pm_domain *domain, bool power_on)
-{
-       struct imx_sc_msg_req_set_resource_power_mode msg;
-       struct imx_sc_rpc_msg *hdr = &msg.hdr;
-       struct imx_sc_pm_domain *pd;
-       int ret;
-
-       pd = to_imx_sc_pd(domain);
-
-       hdr->ver = IMX_SC_RPC_VERSION;
-       hdr->svc = IMX_SC_RPC_SVC_PM;
-       hdr->func = IMX_SC_PM_FUNC_SET_RESOURCE_POWER_MODE;
-       hdr->size = 2;
-
-       msg.resource = pd->rsrc;
-       msg.mode = power_on ? IMX_SC_PM_PW_MODE_ON : IMX_SC_PM_PW_MODE_LP;
-
-       /* keep uart console power on for no_console_suspend */
-       if (imx_con_rsrc == pd->rsrc && !console_suspend_enabled && !power_on)
-               return -EBUSY;
-
-       ret = imx_scu_call_rpc(pm_ipc_handle, &msg, true);
-       if (ret)
-               dev_err(&domain->dev, "failed to power %s resource %d ret %d\n",
-                       power_on ? "up" : "off", pd->rsrc, ret);
-
-       return ret;
-}
-
-static int imx_sc_pd_power_on(struct generic_pm_domain *domain)
-{
-       return imx_sc_pd_power(domain, true);
-}
-
-static int imx_sc_pd_power_off(struct generic_pm_domain *domain)
-{
-       return imx_sc_pd_power(domain, false);
-}
-
-static struct generic_pm_domain *imx_scu_pd_xlate(struct of_phandle_args *spec,
-                                                 void *data)
-{
-       struct generic_pm_domain *domain = ERR_PTR(-ENOENT);
-       struct genpd_onecell_data *pd_data = data;
-       unsigned int i;
-
-       for (i = 0; i < pd_data->num_domains; i++) {
-               struct imx_sc_pm_domain *sc_pd;
-
-               sc_pd = to_imx_sc_pd(pd_data->domains[i]);
-               if (sc_pd->rsrc == spec->args[0]) {
-                       domain = &sc_pd->pd;
-                       break;
-               }
-       }
-
-       return domain;
-}
-
-static struct imx_sc_pm_domain *
-imx_scu_add_pm_domain(struct device *dev, int idx,
-                     const struct imx_sc_pd_range *pd_ranges)
-{
-       struct imx_sc_pm_domain *sc_pd;
-       bool is_off;
-       int mode, ret;
-
-       if (!imx_sc_rm_is_resource_owned(pm_ipc_handle, pd_ranges->rsrc + idx))
-               return NULL;
-
-       sc_pd = devm_kzalloc(dev, sizeof(*sc_pd), GFP_KERNEL);
-       if (!sc_pd)
-               return ERR_PTR(-ENOMEM);
-
-       sc_pd->rsrc = pd_ranges->rsrc + idx;
-       sc_pd->pd.power_off = imx_sc_pd_power_off;
-       sc_pd->pd.power_on = imx_sc_pd_power_on;
-
-       if (pd_ranges->postfix)
-               snprintf(sc_pd->name, sizeof(sc_pd->name),
-                        "%s%i", pd_ranges->name, pd_ranges->start_from + idx);
-       else
-               snprintf(sc_pd->name, sizeof(sc_pd->name),
-                        "%s", pd_ranges->name);
-
-       sc_pd->pd.name = sc_pd->name;
-       if (imx_con_rsrc == sc_pd->rsrc)
-               sc_pd->pd.flags = GENPD_FLAG_RPM_ALWAYS_ON;
-
-       mode = imx_sc_get_pd_power(dev, pd_ranges->rsrc + idx);
-       if (mode == IMX_SC_PM_PW_MODE_ON)
-               is_off = false;
-       else
-               is_off = true;
-
-       dev_dbg(dev, "%s : %s\n", sc_pd->name, imx_sc_pm_mode[mode]);
-
-       if (sc_pd->rsrc >= IMX_SC_R_LAST) {
-               dev_warn(dev, "invalid pd %s rsrc id %d found",
-                        sc_pd->name, sc_pd->rsrc);
-
-               devm_kfree(dev, sc_pd);
-               return NULL;
-       }
-
-       ret = pm_genpd_init(&sc_pd->pd, NULL, is_off);
-       if (ret) {
-               dev_warn(dev, "failed to init pd %s rsrc id %d",
-                        sc_pd->name, sc_pd->rsrc);
-               devm_kfree(dev, sc_pd);
-               return NULL;
-       }
-
-       return sc_pd;
-}
-
-static int imx_scu_init_pm_domains(struct device *dev,
-                                   const struct imx_sc_pd_soc *pd_soc)
-{
-       const struct imx_sc_pd_range *pd_ranges = pd_soc->pd_ranges;
-       struct generic_pm_domain **domains;
-       struct genpd_onecell_data *pd_data;
-       struct imx_sc_pm_domain *sc_pd;
-       u32 count = 0;
-       int i, j;
-
-       for (i = 0; i < pd_soc->num_ranges; i++)
-               count += pd_ranges[i].num;
-
-       domains = devm_kcalloc(dev, count, sizeof(*domains), GFP_KERNEL);
-       if (!domains)
-               return -ENOMEM;
-
-       pd_data = devm_kzalloc(dev, sizeof(*pd_data), GFP_KERNEL);
-       if (!pd_data)
-               return -ENOMEM;
-
-       count = 0;
-       for (i = 0; i < pd_soc->num_ranges; i++) {
-               for (j = 0; j < pd_ranges[i].num; j++) {
-                       sc_pd = imx_scu_add_pm_domain(dev, j, &pd_ranges[i]);
-                       if (IS_ERR_OR_NULL(sc_pd))
-                               continue;
-
-                       domains[count++] = &sc_pd->pd;
-                       dev_dbg(dev, "added power domain %s\n", sc_pd->pd.name);
-               }
-       }
-
-       pd_data->domains = domains;
-       pd_data->num_domains = count;
-       pd_data->xlate = imx_scu_pd_xlate;
-
-       of_genpd_add_provider_onecell(dev->of_node, pd_data);
-
-       return 0;
-}
-
-static int imx_sc_pd_probe(struct platform_device *pdev)
-{
-       const struct imx_sc_pd_soc *pd_soc;
-       int ret;
-
-       ret = imx_scu_get_handle(&pm_ipc_handle);
-       if (ret)
-               return ret;
-
-       pd_soc = of_device_get_match_data(&pdev->dev);
-       if (!pd_soc)
-               return -ENODEV;
-
-       imx_sc_pd_get_console_rsrc();
-
-       return imx_scu_init_pm_domains(&pdev->dev, pd_soc);
-}
-
-static const struct of_device_id imx_sc_pd_match[] = {
-       { .compatible = "fsl,imx8qxp-scu-pd", &imx8qxp_scu_pd},
-       { .compatible = "fsl,scu-pd", &imx8qxp_scu_pd},
-       { /* sentinel */ }
-};
-
-static struct platform_driver imx_sc_pd_driver = {
-       .driver = {
-               .name = "imx-scu-pd",
-               .of_match_table = imx_sc_pd_match,
-               .suppress_bind_attrs = true,
-       },
-       .probe = imx_sc_pd_probe,
-};
-builtin_platform_driver(imx_sc_pd_driver);
-
-MODULE_AUTHOR("Dong Aisheng <aisheng.dong@nxp.com>");
-MODULE_DESCRIPTION("IMX SCU Power Domain driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/genpd/mediatek/Makefile b/drivers/genpd/mediatek/Makefile
deleted file mode 100644 (file)
index 8cde09e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_MTK_SCPSYS)               += mtk-scpsys.o
-obj-$(CONFIG_MTK_SCPSYS_PM_DOMAINS)    += mtk-pm-domains.o
diff --git a/drivers/genpd/mediatek/mt6795-pm-domains.h b/drivers/genpd/mediatek/mt6795-pm-domains.h
deleted file mode 100644 (file)
index ef07c9d..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef __SOC_MEDIATEK_MT6795_PM_DOMAINS_H
-#define __SOC_MEDIATEK_MT6795_PM_DOMAINS_H
-
-#include "mtk-pm-domains.h"
-#include <dt-bindings/power/mt6795-power.h>
-
-/*
- * MT6795 power domain support
- */
-
-static const struct scpsys_domain_data scpsys_domain_data_mt6795[] = {
-       [MT6795_POWER_DOMAIN_VDEC] = {
-               .name = "vdec",
-               .sta_mask = PWR_STATUS_VDEC,
-               .ctl_offs = SPM_VDE_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-       },
-       [MT6795_POWER_DOMAIN_VENC] = {
-               .name = "venc",
-               .sta_mask = PWR_STATUS_VENC,
-               .ctl_offs = SPM_VEN_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-       },
-       [MT6795_POWER_DOMAIN_ISP] = {
-               .name = "isp",
-               .sta_mask = PWR_STATUS_ISP,
-               .ctl_offs = SPM_ISP_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(13, 12),
-       },
-       [MT6795_POWER_DOMAIN_MM] = {
-               .name = "mm",
-               .sta_mask = PWR_STATUS_DISP,
-               .ctl_offs = SPM_DIS_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MM_M0 |
-                                              MT8173_TOP_AXI_PROT_EN_MM_M1),
-               },
-       },
-       [MT6795_POWER_DOMAIN_MJC] = {
-               .name = "mjc",
-               .sta_mask = BIT(20),
-               .ctl_offs = 0x298,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-       },
-       [MT6795_POWER_DOMAIN_AUDIO] = {
-               .name = "audio",
-               .sta_mask = PWR_STATUS_AUDIO,
-               .ctl_offs = SPM_AUDIO_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-       },
-       [MT6795_POWER_DOMAIN_MFG_ASYNC] = {
-               .name = "mfg_async",
-               .sta_mask = PWR_STATUS_MFG_ASYNC,
-               .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = 0,
-       },
-       [MT6795_POWER_DOMAIN_MFG_2D] = {
-               .name = "mfg_2d",
-               .sta_mask = PWR_STATUS_MFG_2D,
-               .ctl_offs = SPM_MFG_2D_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(13, 12),
-       },
-       [MT6795_POWER_DOMAIN_MFG] = {
-               .name = "mfg",
-               .sta_mask = PWR_STATUS_MFG,
-               .ctl_offs = SPM_MFG_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(13, 8),
-               .sram_pdn_ack_bits = GENMASK(21, 16),
-               .bp_infracfg = {
-                       BUS_PROT_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MFG_S |
-                                              MT8173_TOP_AXI_PROT_EN_MFG_M0 |
-                                              MT8173_TOP_AXI_PROT_EN_MFG_M1 |
-                                              MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT),
-               },
-       },
-};
-
-static const struct scpsys_soc_data mt6795_scpsys_data = {
-       .domains_data = scpsys_domain_data_mt6795,
-       .num_domains = ARRAY_SIZE(scpsys_domain_data_mt6795),
-};
-
-#endif /* __SOC_MEDIATEK_MT6795_PM_DOMAINS_H */
diff --git a/drivers/genpd/mediatek/mt8167-pm-domains.h b/drivers/genpd/mediatek/mt8167-pm-domains.h
deleted file mode 100644 (file)
index 4d6c327..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef __SOC_MEDIATEK_MT8167_PM_DOMAINS_H
-#define __SOC_MEDIATEK_MT8167_PM_DOMAINS_H
-
-#include "mtk-pm-domains.h"
-#include <dt-bindings/power/mt8167-power.h>
-
-#define MT8167_PWR_STATUS_MFG_2D       BIT(24)
-#define MT8167_PWR_STATUS_MFG_ASYNC    BIT(25)
-
-/*
- * MT8167 power domain support
- */
-
-static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = {
-       [MT8167_POWER_DOMAIN_MM] = {
-               .name = "mm",
-               .sta_mask = PWR_STATUS_DISP,
-               .ctl_offs = SPM_DIS_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_MM_EMI |
-                                              MT8167_TOP_AXI_PROT_EN_MCU_MM),
-               },
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT8167_POWER_DOMAIN_VDEC] = {
-               .name = "vdec",
-               .sta_mask = PWR_STATUS_VDEC,
-               .ctl_offs = SPM_VDE_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT8167_POWER_DOMAIN_ISP] = {
-               .name = "isp",
-               .sta_mask = PWR_STATUS_ISP,
-               .ctl_offs = SPM_ISP_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(13, 12),
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT8167_POWER_DOMAIN_MFG_ASYNC] = {
-               .name = "mfg_async",
-               .sta_mask = MT8167_PWR_STATUS_MFG_ASYNC,
-               .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = 0,
-               .sram_pdn_ack_bits = 0,
-               .bp_infracfg = {
-                       BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_MCU_MFG |
-                                              MT8167_TOP_AXI_PROT_EN_MFG_EMI),
-               },
-       },
-       [MT8167_POWER_DOMAIN_MFG_2D] = {
-               .name = "mfg_2d",
-               .sta_mask = MT8167_PWR_STATUS_MFG_2D,
-               .ctl_offs = SPM_MFG_2D_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-       },
-       [MT8167_POWER_DOMAIN_MFG] = {
-               .name = "mfg",
-               .sta_mask = PWR_STATUS_MFG,
-               .ctl_offs = SPM_MFG_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-       },
-       [MT8167_POWER_DOMAIN_CONN] = {
-               .name = "conn",
-               .sta_mask = PWR_STATUS_CONN,
-               .ctl_offs = SPM_CONN_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = 0,
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-               .bp_infracfg = {
-                       BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_CONN_EMI |
-                                              MT8167_TOP_AXI_PROT_EN_CONN_MCU |
-                                              MT8167_TOP_AXI_PROT_EN_MCU_CONN),
-               },
-       },
-};
-
-static const struct scpsys_soc_data mt8167_scpsys_data = {
-       .domains_data = scpsys_domain_data_mt8167,
-       .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8167),
-};
-
-#endif /* __SOC_MEDIATEK_MT8167_PM_DOMAINS_H */
-
diff --git a/drivers/genpd/mediatek/mt8173-pm-domains.h b/drivers/genpd/mediatek/mt8173-pm-domains.h
deleted file mode 100644 (file)
index 1a5dc63..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef __SOC_MEDIATEK_MT8173_PM_DOMAINS_H
-#define __SOC_MEDIATEK_MT8173_PM_DOMAINS_H
-
-#include "mtk-pm-domains.h"
-#include <dt-bindings/power/mt8173-power.h>
-
-/*
- * MT8173 power domain support
- */
-
-static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = {
-       [MT8173_POWER_DOMAIN_VDEC] = {
-               .name = "vdec",
-               .sta_mask = PWR_STATUS_VDEC,
-               .ctl_offs = SPM_VDE_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-       },
-       [MT8173_POWER_DOMAIN_VENC] = {
-               .name = "venc",
-               .sta_mask = PWR_STATUS_VENC,
-               .ctl_offs = SPM_VEN_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-       },
-       [MT8173_POWER_DOMAIN_ISP] = {
-               .name = "isp",
-               .sta_mask = PWR_STATUS_ISP,
-               .ctl_offs = SPM_ISP_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(13, 12),
-       },
-       [MT8173_POWER_DOMAIN_MM] = {
-               .name = "mm",
-               .sta_mask = PWR_STATUS_DISP,
-               .ctl_offs = SPM_DIS_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MM_M0 |
-                                              MT8173_TOP_AXI_PROT_EN_MM_M1),
-               },
-       },
-       [MT8173_POWER_DOMAIN_VENC_LT] = {
-               .name = "venc_lt",
-               .sta_mask = PWR_STATUS_VENC_LT,
-               .ctl_offs = SPM_VEN2_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-       },
-       [MT8173_POWER_DOMAIN_AUDIO] = {
-               .name = "audio",
-               .sta_mask = PWR_STATUS_AUDIO,
-               .ctl_offs = SPM_AUDIO_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-       },
-       [MT8173_POWER_DOMAIN_USB] = {
-               .name = "usb",
-               .sta_mask = PWR_STATUS_USB,
-               .ctl_offs = SPM_USB_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT8173_POWER_DOMAIN_MFG_ASYNC] = {
-               .name = "mfg_async",
-               .sta_mask = PWR_STATUS_MFG_ASYNC,
-               .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = 0,
-               .caps = MTK_SCPD_DOMAIN_SUPPLY,
-       },
-       [MT8173_POWER_DOMAIN_MFG_2D] = {
-               .name = "mfg_2d",
-               .sta_mask = PWR_STATUS_MFG_2D,
-               .ctl_offs = SPM_MFG_2D_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(13, 12),
-       },
-       [MT8173_POWER_DOMAIN_MFG] = {
-               .name = "mfg",
-               .sta_mask = PWR_STATUS_MFG,
-               .ctl_offs = SPM_MFG_PWR_CON,
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
-               .sram_pdn_bits = GENMASK(13, 8),
-               .sram_pdn_ack_bits = GENMASK(21, 16),
-               .bp_infracfg = {
-                       BUS_PROT_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MFG_S |
-                                              MT8173_TOP_AXI_PROT_EN_MFG_M0 |
-                                              MT8173_TOP_AXI_PROT_EN_MFG_M1 |
-                                              MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT),
-               },
-       },
-};
-
-static const struct scpsys_soc_data mt8173_scpsys_data = {
-       .domains_data = scpsys_domain_data_mt8173,
-       .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8173),
-};
-
-#endif /* __SOC_MEDIATEK_MT8173_PM_DOMAINS_H */
diff --git a/drivers/genpd/mediatek/mt8183-pm-domains.h b/drivers/genpd/mediatek/mt8183-pm-domains.h
deleted file mode 100644 (file)
index 99de67f..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef __SOC_MEDIATEK_MT8183_PM_DOMAINS_H
-#define __SOC_MEDIATEK_MT8183_PM_DOMAINS_H
-
-#include "mtk-pm-domains.h"
-#include <dt-bindings/power/mt8183-power.h>
-
-/*
- * MT8183 power domain support
- */
-
-static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = {
-       [MT8183_POWER_DOMAIN_AUDIO] = {
-               .name = "audio",
-               .sta_mask = PWR_STATUS_AUDIO,
-               .ctl_offs = 0x0314,
-               .pwr_sta_offs = 0x0180,
-               .pwr_sta2nd_offs = 0x0184,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-       },
-       [MT8183_POWER_DOMAIN_CONN] = {
-               .name = "conn",
-               .sta_mask = PWR_STATUS_CONN,
-               .ctl_offs = 0x032c,
-               .pwr_sta_offs = 0x0180,
-               .pwr_sta2nd_offs = 0x0184,
-               .sram_pdn_bits = 0,
-               .sram_pdn_ack_bits = 0,
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_CONN, MT8183_TOP_AXI_PROT_EN_SET,
-                                   MT8183_TOP_AXI_PROT_EN_CLR, MT8183_TOP_AXI_PROT_EN_STA1),
-               },
-       },
-       [MT8183_POWER_DOMAIN_MFG_ASYNC] = {
-               .name = "mfg_async",
-               .sta_mask = PWR_STATUS_MFG_ASYNC,
-               .ctl_offs = 0x0334,
-               .pwr_sta_offs = 0x0180,
-               .pwr_sta2nd_offs = 0x0184,
-               .sram_pdn_bits = 0,
-               .sram_pdn_ack_bits = 0,
-               .caps = MTK_SCPD_DOMAIN_SUPPLY,
-       },
-       [MT8183_POWER_DOMAIN_MFG] = {
-               .name = "mfg",
-               .sta_mask = PWR_STATUS_MFG,
-               .ctl_offs = 0x0338,
-               .pwr_sta_offs = 0x0180,
-               .pwr_sta2nd_offs = 0x0184,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .caps = MTK_SCPD_DOMAIN_SUPPLY,
-       },
-       [MT8183_POWER_DOMAIN_MFG_CORE0] = {
-               .name = "mfg_core0",
-               .sta_mask = BIT(7),
-               .ctl_offs = 0x034c,
-               .pwr_sta_offs = 0x0180,
-               .pwr_sta2nd_offs = 0x0184,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-       },
-       [MT8183_POWER_DOMAIN_MFG_CORE1] = {
-               .name = "mfg_core1",
-               .sta_mask = BIT(20),
-               .ctl_offs = 0x0310,
-               .pwr_sta_offs = 0x0180,
-               .pwr_sta2nd_offs = 0x0184,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-       },
-       [MT8183_POWER_DOMAIN_MFG_2D] = {
-               .name = "mfg_2d",
-               .sta_mask = PWR_STATUS_MFG_2D,
-               .ctl_offs = 0x0348,
-               .pwr_sta_offs = 0x0180,
-               .pwr_sta2nd_offs = 0x0184,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_1_MFG, MT8183_TOP_AXI_PROT_EN_1_SET,
-                                   MT8183_TOP_AXI_PROT_EN_1_CLR, MT8183_TOP_AXI_PROT_EN_STA1_1),
-                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MFG, MT8183_TOP_AXI_PROT_EN_SET,
-                                   MT8183_TOP_AXI_PROT_EN_CLR, MT8183_TOP_AXI_PROT_EN_STA1),
-               },
-       },
-       [MT8183_POWER_DOMAIN_DISP] = {
-               .name = "disp",
-               .sta_mask = PWR_STATUS_DISP,
-               .ctl_offs = 0x030c,
-               .pwr_sta_offs = 0x0180,
-               .pwr_sta2nd_offs = 0x0184,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_1_DISP, MT8183_TOP_AXI_PROT_EN_1_SET,
-                                   MT8183_TOP_AXI_PROT_EN_1_CLR, MT8183_TOP_AXI_PROT_EN_STA1_1),
-                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_DISP, MT8183_TOP_AXI_PROT_EN_SET,
-                                   MT8183_TOP_AXI_PROT_EN_CLR, MT8183_TOP_AXI_PROT_EN_STA1),
-               },
-               .bp_smi = {
-                       BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_DISP,
-                                   MT8183_SMI_COMMON_CLAMP_EN_SET,
-                                   MT8183_SMI_COMMON_CLAMP_EN_CLR,
-                                   MT8183_SMI_COMMON_CLAMP_EN),
-               },
-       },
-       [MT8183_POWER_DOMAIN_CAM] = {
-               .name = "cam",
-               .sta_mask = BIT(25),
-               .ctl_offs = 0x0344,
-               .pwr_sta_offs = 0x0180,
-               .pwr_sta2nd_offs = 0x0184,
-               .sram_pdn_bits = GENMASK(9, 8),
-               .sram_pdn_ack_bits = GENMASK(13, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MM_CAM, MT8183_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8183_TOP_AXI_PROT_EN_MM_CLR, MT8183_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_CAM, MT8183_TOP_AXI_PROT_EN_SET,
-                                   MT8183_TOP_AXI_PROT_EN_CLR, MT8183_TOP_AXI_PROT_EN_STA1),
-                       BUS_PROT_WR_IGN(MT8183_TOP_AXI_PROT_EN_MM_CAM_2ND,
-                                       MT8183_TOP_AXI_PROT_EN_MM_SET,
-                                       MT8183_TOP_AXI_PROT_EN_MM_CLR,
-                                       MT8183_TOP_AXI_PROT_EN_MM_STA1),
-               },
-               .bp_smi = {
-                       BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_CAM,
-                                   MT8183_SMI_COMMON_CLAMP_EN_SET,
-                                   MT8183_SMI_COMMON_CLAMP_EN_CLR,
-                                   MT8183_SMI_COMMON_CLAMP_EN),
-               },
-       },
-       [MT8183_POWER_DOMAIN_ISP] = {
-               .name = "isp",
-               .sta_mask = PWR_STATUS_ISP,
-               .ctl_offs = 0x0308,
-               .pwr_sta_offs = 0x0180,
-               .pwr_sta2nd_offs = 0x0184,
-               .sram_pdn_bits = GENMASK(9, 8),
-               .sram_pdn_ack_bits = GENMASK(13, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MM_ISP,
-                                   MT8183_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8183_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8183_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR_IGN(MT8183_TOP_AXI_PROT_EN_MM_ISP_2ND,
-                                       MT8183_TOP_AXI_PROT_EN_MM_SET,
-                                       MT8183_TOP_AXI_PROT_EN_MM_CLR,
-                                       MT8183_TOP_AXI_PROT_EN_MM_STA1),
-               },
-               .bp_smi = {
-                       BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_ISP,
-                                   MT8183_SMI_COMMON_CLAMP_EN_SET,
-                                   MT8183_SMI_COMMON_CLAMP_EN_CLR,
-                                   MT8183_SMI_COMMON_CLAMP_EN),
-               },
-       },
-       [MT8183_POWER_DOMAIN_VDEC] = {
-               .name = "vdec",
-               .sta_mask = BIT(31),
-               .ctl_offs = 0x0300,
-               .pwr_sta_offs = 0x0180,
-               .pwr_sta2nd_offs = 0x0184,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_smi = {
-                       BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_VDEC,
-                                   MT8183_SMI_COMMON_CLAMP_EN_SET,
-                                   MT8183_SMI_COMMON_CLAMP_EN_CLR,
-                                   MT8183_SMI_COMMON_CLAMP_EN),
-               },
-       },
-       [MT8183_POWER_DOMAIN_VENC] = {
-               .name = "venc",
-               .sta_mask = PWR_STATUS_VENC,
-               .ctl_offs = 0x0304,
-               .pwr_sta_offs = 0x0180,
-               .pwr_sta2nd_offs = 0x0184,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .bp_smi = {
-                       BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_VENC,
-                                   MT8183_SMI_COMMON_CLAMP_EN_SET,
-                                   MT8183_SMI_COMMON_CLAMP_EN_CLR,
-                                   MT8183_SMI_COMMON_CLAMP_EN),
-               },
-       },
-       [MT8183_POWER_DOMAIN_VPU_TOP] = {
-               .name = "vpu_top",
-               .sta_mask = BIT(26),
-               .ctl_offs = 0x0324,
-               .pwr_sta_offs = 0x0180,
-               .pwr_sta2nd_offs = 0x0184,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MM_VPU_TOP,
-                                   MT8183_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8183_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8183_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_VPU_TOP,
-                                   MT8183_TOP_AXI_PROT_EN_SET,
-                                   MT8183_TOP_AXI_PROT_EN_CLR,
-                                   MT8183_TOP_AXI_PROT_EN_STA1),
-                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MM_VPU_TOP_2ND,
-                                   MT8183_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8183_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8183_TOP_AXI_PROT_EN_MM_STA1),
-               },
-               .bp_smi = {
-                       BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_VPU_TOP,
-                                   MT8183_SMI_COMMON_CLAMP_EN_SET,
-                                   MT8183_SMI_COMMON_CLAMP_EN_CLR,
-                                   MT8183_SMI_COMMON_CLAMP_EN),
-               },
-       },
-       [MT8183_POWER_DOMAIN_VPU_CORE0] = {
-               .name = "vpu_core0",
-               .sta_mask = BIT(27),
-               .ctl_offs = 0x33c,
-               .pwr_sta_offs = 0x0180,
-               .pwr_sta2nd_offs = 0x0184,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(13, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE0,
-                                   MT8183_TOP_AXI_PROT_EN_MCU_SET,
-                                   MT8183_TOP_AXI_PROT_EN_MCU_CLR,
-                                   MT8183_TOP_AXI_PROT_EN_MCU_STA1),
-                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE0_2ND,
-                                   MT8183_TOP_AXI_PROT_EN_MCU_SET,
-                                   MT8183_TOP_AXI_PROT_EN_MCU_CLR,
-                                   MT8183_TOP_AXI_PROT_EN_MCU_STA1),
-               },
-               .caps = MTK_SCPD_SRAM_ISO,
-       },
-       [MT8183_POWER_DOMAIN_VPU_CORE1] = {
-               .name = "vpu_core1",
-               .sta_mask = BIT(28),
-               .ctl_offs = 0x0340,
-               .pwr_sta_offs = 0x0180,
-               .pwr_sta2nd_offs = 0x0184,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(13, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE1,
-                                   MT8183_TOP_AXI_PROT_EN_MCU_SET,
-                                   MT8183_TOP_AXI_PROT_EN_MCU_CLR,
-                                   MT8183_TOP_AXI_PROT_EN_MCU_STA1),
-                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE1_2ND,
-                                   MT8183_TOP_AXI_PROT_EN_MCU_SET,
-                                   MT8183_TOP_AXI_PROT_EN_MCU_CLR,
-                                   MT8183_TOP_AXI_PROT_EN_MCU_STA1),
-               },
-               .caps = MTK_SCPD_SRAM_ISO,
-       },
-};
-
-static const struct scpsys_soc_data mt8183_scpsys_data = {
-       .domains_data = scpsys_domain_data_mt8183,
-       .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8183),
-};
-
-#endif /* __SOC_MEDIATEK_MT8183_PM_DOMAINS_H */
diff --git a/drivers/genpd/mediatek/mt8186-pm-domains.h b/drivers/genpd/mediatek/mt8186-pm-domains.h
deleted file mode 100644 (file)
index fce86f7..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2022 MediaTek Inc.
- * Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
- */
-
-#ifndef __SOC_MEDIATEK_MT8186_PM_DOMAINS_H
-#define __SOC_MEDIATEK_MT8186_PM_DOMAINS_H
-
-#include "mtk-pm-domains.h"
-#include <dt-bindings/power/mt8186-power.h>
-
-/*
- * MT8186 power domain support
- */
-
-static const struct scpsys_domain_data scpsys_domain_data_mt8186[] = {
-       [MT8186_POWER_DOMAIN_MFG0] = {
-               .name = "mfg0",
-               .sta_mask = BIT(2),
-               .ctl_offs = 0x308,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
-       },
-       [MT8186_POWER_DOMAIN_MFG1] = {
-               .name = "mfg1",
-               .sta_mask = BIT(3),
-               .ctl_offs = 0x30c,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_MFG1_STEP1,
-                               MT8186_TOP_AXI_PROT_EN_1_SET,
-                               MT8186_TOP_AXI_PROT_EN_1_CLR,
-                               MT8186_TOP_AXI_PROT_EN_1_STA),
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_MFG1_STEP2,
-                               MT8186_TOP_AXI_PROT_EN_SET,
-                               MT8186_TOP_AXI_PROT_EN_CLR,
-                               MT8186_TOP_AXI_PROT_EN_STA),
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_MFG1_STEP3,
-                               MT8186_TOP_AXI_PROT_EN_SET,
-                               MT8186_TOP_AXI_PROT_EN_CLR,
-                               MT8186_TOP_AXI_PROT_EN_STA),
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_MFG1_STEP4,
-                               MT8186_TOP_AXI_PROT_EN_1_SET,
-                               MT8186_TOP_AXI_PROT_EN_1_CLR,
-                               MT8186_TOP_AXI_PROT_EN_1_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
-       },
-       [MT8186_POWER_DOMAIN_MFG2] = {
-               .name = "mfg2",
-               .sta_mask = BIT(4),
-               .ctl_offs = 0x310,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8186_POWER_DOMAIN_MFG3] = {
-               .name = "mfg3",
-               .sta_mask = BIT(5),
-               .ctl_offs = 0x314,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8186_POWER_DOMAIN_SSUSB] = {
-               .name = "ssusb",
-               .sta_mask = BIT(20),
-               .ctl_offs = 0x9F0,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT8186_POWER_DOMAIN_SSUSB_P1] = {
-               .name = "ssusb_p1",
-               .sta_mask = BIT(19),
-               .ctl_offs = 0x9F4,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT8186_POWER_DOMAIN_DIS] = {
-               .name = "dis",
-               .sta_mask = BIT(21),
-               .ctl_offs = 0x354,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_DIS_STEP1,
-                               MT8186_TOP_AXI_PROT_EN_1_SET,
-                               MT8186_TOP_AXI_PROT_EN_1_CLR,
-                               MT8186_TOP_AXI_PROT_EN_1_STA),
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_DIS_STEP2,
-                               MT8186_TOP_AXI_PROT_EN_SET,
-                               MT8186_TOP_AXI_PROT_EN_CLR,
-                               MT8186_TOP_AXI_PROT_EN_STA),
-               },
-       },
-       [MT8186_POWER_DOMAIN_IMG] = {
-               .name = "img",
-               .sta_mask = BIT(13),
-               .ctl_offs = 0x334,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_IMG_STEP1,
-                               MT8186_TOP_AXI_PROT_EN_1_SET,
-                               MT8186_TOP_AXI_PROT_EN_1_CLR,
-                               MT8186_TOP_AXI_PROT_EN_1_STA),
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_IMG_STEP2,
-                               MT8186_TOP_AXI_PROT_EN_1_SET,
-                               MT8186_TOP_AXI_PROT_EN_1_CLR,
-                               MT8186_TOP_AXI_PROT_EN_1_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8186_POWER_DOMAIN_IMG2] = {
-               .name = "img2",
-               .sta_mask = BIT(14),
-               .ctl_offs = 0x338,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8186_POWER_DOMAIN_IPE] = {
-               .name = "ipe",
-               .sta_mask = BIT(15),
-               .ctl_offs = 0x33C,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_IPE_STEP1,
-                               MT8186_TOP_AXI_PROT_EN_1_SET,
-                               MT8186_TOP_AXI_PROT_EN_1_CLR,
-                               MT8186_TOP_AXI_PROT_EN_1_STA),
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_IPE_STEP2,
-                               MT8186_TOP_AXI_PROT_EN_1_SET,
-                               MT8186_TOP_AXI_PROT_EN_1_CLR,
-                               MT8186_TOP_AXI_PROT_EN_1_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8186_POWER_DOMAIN_CAM] = {
-               .name = "cam",
-               .sta_mask = BIT(23),
-               .ctl_offs = 0x35C,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_CAM_STEP1,
-                               MT8186_TOP_AXI_PROT_EN_1_SET,
-                               MT8186_TOP_AXI_PROT_EN_1_CLR,
-                               MT8186_TOP_AXI_PROT_EN_1_STA),
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_CAM_STEP2,
-                               MT8186_TOP_AXI_PROT_EN_1_SET,
-                               MT8186_TOP_AXI_PROT_EN_1_CLR,
-                               MT8186_TOP_AXI_PROT_EN_1_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8186_POWER_DOMAIN_CAM_RAWA] = {
-               .name = "cam_rawa",
-               .sta_mask = BIT(24),
-               .ctl_offs = 0x360,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8186_POWER_DOMAIN_CAM_RAWB] = {
-               .name = "cam_rawb",
-               .sta_mask = BIT(25),
-               .ctl_offs = 0x364,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8186_POWER_DOMAIN_VENC] = {
-               .name = "venc",
-               .sta_mask = BIT(18),
-               .ctl_offs = 0x348,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_VENC_STEP1,
-                               MT8186_TOP_AXI_PROT_EN_1_SET,
-                               MT8186_TOP_AXI_PROT_EN_1_CLR,
-                               MT8186_TOP_AXI_PROT_EN_1_STA),
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_VENC_STEP2,
-                               MT8186_TOP_AXI_PROT_EN_1_SET,
-                               MT8186_TOP_AXI_PROT_EN_1_CLR,
-                               MT8186_TOP_AXI_PROT_EN_1_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8186_POWER_DOMAIN_VDEC] = {
-               .name = "vdec",
-               .sta_mask = BIT(16),
-               .ctl_offs = 0x340,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_VDEC_STEP1,
-                               MT8186_TOP_AXI_PROT_EN_1_SET,
-                               MT8186_TOP_AXI_PROT_EN_1_CLR,
-                               MT8186_TOP_AXI_PROT_EN_1_STA),
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_VDEC_STEP2,
-                               MT8186_TOP_AXI_PROT_EN_1_SET,
-                               MT8186_TOP_AXI_PROT_EN_1_CLR,
-                               MT8186_TOP_AXI_PROT_EN_1_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8186_POWER_DOMAIN_WPE] = {
-               .name = "wpe",
-               .sta_mask = BIT(0),
-               .ctl_offs = 0x3F8,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_2_WPE_STEP1,
-                               MT8186_TOP_AXI_PROT_EN_2_SET,
-                               MT8186_TOP_AXI_PROT_EN_2_CLR,
-                               MT8186_TOP_AXI_PROT_EN_2_STA),
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_2_WPE_STEP2,
-                               MT8186_TOP_AXI_PROT_EN_2_SET,
-                               MT8186_TOP_AXI_PROT_EN_2_CLR,
-                               MT8186_TOP_AXI_PROT_EN_2_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8186_POWER_DOMAIN_CONN_ON] = {
-               .name = "conn_on",
-               .sta_mask = BIT(1),
-               .ctl_offs = 0x304,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .bp_infracfg = {
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_CONN_ON_STEP1,
-                               MT8186_TOP_AXI_PROT_EN_1_SET,
-                               MT8186_TOP_AXI_PROT_EN_1_CLR,
-                               MT8186_TOP_AXI_PROT_EN_1_STA),
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP2,
-                               MT8186_TOP_AXI_PROT_EN_SET,
-                               MT8186_TOP_AXI_PROT_EN_CLR,
-                               MT8186_TOP_AXI_PROT_EN_STA),
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP3,
-                               MT8186_TOP_AXI_PROT_EN_SET,
-                               MT8186_TOP_AXI_PROT_EN_CLR,
-                               MT8186_TOP_AXI_PROT_EN_STA),
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP4,
-                               MT8186_TOP_AXI_PROT_EN_SET,
-                               MT8186_TOP_AXI_PROT_EN_CLR,
-                               MT8186_TOP_AXI_PROT_EN_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT8186_POWER_DOMAIN_CSIRX_TOP] = {
-               .name = "csirx_top",
-               .sta_mask = BIT(6),
-               .ctl_offs = 0x318,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8186_POWER_DOMAIN_ADSP_AO] = {
-               .name = "adsp_ao",
-               .sta_mask = BIT(17),
-               .ctl_offs = 0x9FC,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-       },
-       [MT8186_POWER_DOMAIN_ADSP_INFRA] = {
-               .name = "adsp_infra",
-               .sta_mask = BIT(10),
-               .ctl_offs = 0x9F8,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-       },
-       [MT8186_POWER_DOMAIN_ADSP_TOP] = {
-               .name = "adsp_top",
-               .sta_mask = BIT(31),
-               .ctl_offs = 0x3E4,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_3_ADSP_TOP_STEP1,
-                               MT8186_TOP_AXI_PROT_EN_3_SET,
-                               MT8186_TOP_AXI_PROT_EN_3_CLR,
-                               MT8186_TOP_AXI_PROT_EN_3_STA),
-                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_3_ADSP_TOP_STEP2,
-                               MT8186_TOP_AXI_PROT_EN_3_SET,
-                               MT8186_TOP_AXI_PROT_EN_3_CLR,
-                               MT8186_TOP_AXI_PROT_EN_3_STA),
-               },
-               .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_ACTIVE_WAKEUP,
-       },
-};
-
-static const struct scpsys_soc_data mt8186_scpsys_data = {
-       .domains_data = scpsys_domain_data_mt8186,
-       .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8186),
-};
-
-#endif /* __SOC_MEDIATEK_MT8186_PM_DOMAINS_H */
diff --git a/drivers/genpd/mediatek/mt8188-pm-domains.h b/drivers/genpd/mediatek/mt8188-pm-domains.h
deleted file mode 100644 (file)
index 0692cb4..0000000
+++ /dev/null
@@ -1,623 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2022 MediaTek Inc.
- * Author: Garmin Chang <garmin.chang@mediatek.com>
- */
-
-#ifndef __SOC_MEDIATEK_MT8188_PM_DOMAINS_H
-#define __SOC_MEDIATEK_MT8188_PM_DOMAINS_H
-
-#include "mtk-pm-domains.h"
-#include <dt-bindings/power/mediatek,mt8188-power.h>
-
-/*
- * MT8188 power domain support
- */
-
-static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
-       [MT8188_POWER_DOMAIN_MFG0] = {
-               .name = "mfg0",
-               .sta_mask = BIT(1),
-               .ctl_offs = 0x300,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
-       },
-       [MT8188_POWER_DOMAIN_MFG1] = {
-               .name = "mfg1",
-               .sta_mask = BIT(2),
-               .ctl_offs = 0x304,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MFG1_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_SET,
-                                   MT8188_TOP_AXI_PROT_EN_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_MFG1_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_2_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_1_MFG1_STEP3,
-                                   MT8188_TOP_AXI_PROT_EN_1_SET,
-                                   MT8188_TOP_AXI_PROT_EN_1_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_1_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_MFG1_STEP4,
-                                   MT8188_TOP_AXI_PROT_EN_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_2_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MFG1_STEP5,
-                                   MT8188_TOP_AXI_PROT_EN_SET,
-                                   MT8188_TOP_AXI_PROT_EN_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MFG1_STEP6,
-                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
-                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
-       },
-       [MT8188_POWER_DOMAIN_MFG2] = {
-               .name = "mfg2",
-               .sta_mask = BIT(3),
-               .ctl_offs = 0x308,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_MFG3] = {
-               .name = "mfg3",
-               .sta_mask = BIT(4),
-               .ctl_offs = 0x30C,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_MFG4] = {
-               .name = "mfg4",
-               .sta_mask = BIT(5),
-               .ctl_offs = 0x310,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_PEXTP_MAC_P0] = {
-               .name = "pextp_mac_p0",
-               .sta_mask = BIT(10),
-               .ctl_offs = 0x324,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_PEXTP_MAC_P0_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_SET,
-                                   MT8188_TOP_AXI_PROT_EN_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_PEXTP_MAC_P0_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
-                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_PEXTP_PHY_TOP] = {
-               .name = "pextp_phy_top",
-               .sta_mask = BIT(12),
-               .ctl_offs = 0x328,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_CSIRX_TOP] = {
-               .name = "pextp_csirx_top",
-               .sta_mask = BIT(17),
-               .ctl_offs = 0x3C4,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_ETHER] = {
-               .name = "ether",
-               .sta_mask = BIT(1),
-               .ctl_offs = 0x338,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_ETHER_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
-                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT8188_POWER_DOMAIN_HDMI_TX] = {
-               .name = "hdmi_tx",
-               .sta_mask = BIT(18),
-               .ctl_offs = 0x37C,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_HDMI_TX_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
-                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT8188_POWER_DOMAIN_ADSP_AO] = {
-               .name = "adsp_ao",
-               .sta_mask = BIT(10),
-               .ctl_offs = 0x35C,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_AO_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_2_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_AO_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_2_STA),
-               },
-               .caps = MTK_SCPD_ALWAYS_ON,
-       },
-       [MT8188_POWER_DOMAIN_ADSP_INFRA] = {
-               .name = "adsp_infra",
-               .sta_mask = BIT(9),
-               .ctl_offs = 0x358,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_INFRA_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_2_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_INFRA_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_2_STA),
-               },
-               .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_ALWAYS_ON,
-       },
-       [MT8188_POWER_DOMAIN_ADSP] = {
-               .name = "adsp",
-               .sta_mask = BIT(8),
-               .ctl_offs = 0x354,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_2_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_2_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_SRAM_ISO | MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT8188_POWER_DOMAIN_AUDIO] = {
-               .name = "audio",
-               .sta_mask = BIT(6),
-               .ctl_offs = 0x34C,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_2_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_2_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT8188_POWER_DOMAIN_AUDIO_ASRC] = {
-               .name = "audio_asrc",
-               .sta_mask = BIT(7),
-               .ctl_offs = 0x350,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_ASRC_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_2_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_ASRC_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_2_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_VPPSYS0] = {
-               .name = "vppsys0",
-               .sta_mask = BIT(11),
-               .ctl_offs = 0x360,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_VPPSYS0_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_SET,
-                                   MT8188_TOP_AXI_PROT_EN_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS0_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_VPPSYS0_STEP3,
-                                   MT8188_TOP_AXI_PROT_EN_SET,
-                                   MT8188_TOP_AXI_PROT_EN_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS0_STEP4,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VPPSYS0_STEP5,
-                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
-                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA),
-               },
-       },
-       [MT8188_POWER_DOMAIN_VDOSYS0] = {
-               .name = "vdosys0",
-               .sta_mask = BIT(13),
-               .ctl_offs = 0x368,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDOSYS0_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_VDOSYS0_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_SET,
-                                   MT8188_TOP_AXI_PROT_EN_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VDOSYS0_STEP3,
-                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
-                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA),
-               },
-       },
-       [MT8188_POWER_DOMAIN_VDOSYS1] = {
-               .name = "vdosys1",
-               .sta_mask = BIT(14),
-               .ctl_offs = 0x36C,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDOSYS1_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDOSYS1_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VDOSYS1_STEP3,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
-               },
-       },
-       [MT8188_POWER_DOMAIN_DP_TX] = {
-               .name = "dp_tx",
-               .sta_mask = BIT(16),
-               .ctl_offs = 0x374,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_DP_TX_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
-                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_EDP_TX] = {
-               .name = "edp_tx",
-               .sta_mask = BIT(17),
-               .ctl_offs = 0x378,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_EDP_TX_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
-                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_VPPSYS1] = {
-               .name = "vppsys1",
-               .sta_mask = BIT(12),
-               .ctl_offs = 0x364,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VPPSYS1_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VPPSYS1_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS1_STEP3,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
-               },
-       },
-       [MT8188_POWER_DOMAIN_WPE] = {
-               .name = "wpe",
-               .sta_mask = BIT(15),
-               .ctl_offs = 0x370,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_WPE_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_WPE_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_VDEC0] = {
-               .name = "vdec0",
-               .sta_mask = BIT(19),
-               .ctl_offs = 0x380,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDEC0_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VDEC0_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_VDEC1] = {
-               .name = "vdec1",
-               .sta_mask = BIT(20),
-               .ctl_offs = 0x384,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDEC1_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDEC1_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_VENC] = {
-               .name = "venc",
-               .sta_mask = BIT(22),
-               .ctl_offs = 0x38C,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VENC_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VENC_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VENC_STEP3,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_IMG_VCORE] = {
-               .name = "vcore",
-               .sta_mask = BIT(28),
-               .ctl_offs = 0x3A4,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_IMG_VCORE_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_IMG_VCORE_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_IMG_VCORE_STEP3,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
-       },
-       [MT8188_POWER_DOMAIN_IMG_MAIN] = {
-               .name = "img_main",
-               .sta_mask = BIT(29),
-               .ctl_offs = 0x3A8,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_IMG_MAIN_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_IMG_MAIN_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_DIP] = {
-               .name = "dip",
-               .sta_mask = BIT(30),
-               .ctl_offs = 0x3AC,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_IPE] = {
-               .name = "ipe",
-               .sta_mask = BIT(31),
-               .ctl_offs = 0x3B0,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_CAM_VCORE] = {
-               .name = "cam_vcore",
-               .sta_mask = BIT(27),
-               .ctl_offs = 0x3A0,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_CAM_VCORE_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_CAM_VCORE_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_2_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_1_CAM_VCORE_STEP3,
-                                   MT8188_TOP_AXI_PROT_EN_1_SET,
-                                   MT8188_TOP_AXI_PROT_EN_1_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_1_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_CAM_VCORE_STEP4,
-                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_CAM_VCORE_STEP5,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
-       },
-       [MT8188_POWER_DOMAIN_CAM_MAIN] = {
-               .name = "cam_main",
-               .sta_mask = BIT(24),
-               .ctl_offs = 0x394,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_CAM_MAIN_STEP1,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_CAM_MAIN_STEP2,
-                                   MT8188_TOP_AXI_PROT_EN_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_2_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_CAM_MAIN_STEP3,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
-                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_CAM_MAIN_STEP4,
-                                   MT8188_TOP_AXI_PROT_EN_2_SET,
-                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8188_TOP_AXI_PROT_EN_2_STA),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_CAM_SUBA] = {
-               .name = "cam_suba",
-               .sta_mask = BIT(25),
-               .ctl_offs = 0x398,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8188_POWER_DOMAIN_CAM_SUBB] = {
-               .name = "cam_subb",
-               .sta_mask = BIT(26),
-               .ctl_offs = 0x39C,
-               .pwr_sta_offs = 0x16C,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = BIT(8),
-               .sram_pdn_ack_bits = BIT(12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-};
-
-static const struct scpsys_soc_data mt8188_scpsys_data = {
-       .domains_data = scpsys_domain_data_mt8188,
-       .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8188),
-};
-
-#endif /* __SOC_MEDIATEK_MT8188_PM_DOMAINS_H */
diff --git a/drivers/genpd/mediatek/mt8192-pm-domains.h b/drivers/genpd/mediatek/mt8192-pm-domains.h
deleted file mode 100644 (file)
index b97b205..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef __SOC_MEDIATEK_MT8192_PM_DOMAINS_H
-#define __SOC_MEDIATEK_MT8192_PM_DOMAINS_H
-
-#include "mtk-pm-domains.h"
-#include <dt-bindings/power/mt8192-power.h>
-
-/*
- * MT8192 power domain support
- */
-
-static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = {
-       [MT8192_POWER_DOMAIN_AUDIO] = {
-               .name = "audio",
-               .sta_mask = BIT(21),
-               .ctl_offs = 0x0354,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_AUDIO,
-                                   MT8192_TOP_AXI_PROT_EN_2_SET,
-                                   MT8192_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_2_STA1),
-               },
-       },
-       [MT8192_POWER_DOMAIN_CONN] = {
-               .name = "conn",
-               .sta_mask = PWR_STATUS_CONN,
-               .ctl_offs = 0x0304,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = 0,
-               .sram_pdn_ack_bits = 0,
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_CONN,
-                                   MT8192_TOP_AXI_PROT_EN_SET,
-                                   MT8192_TOP_AXI_PROT_EN_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_CONN_2ND,
-                                   MT8192_TOP_AXI_PROT_EN_SET,
-                                   MT8192_TOP_AXI_PROT_EN_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_1_CONN,
-                                   MT8192_TOP_AXI_PROT_EN_1_SET,
-                                   MT8192_TOP_AXI_PROT_EN_1_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_1_STA1),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8192_POWER_DOMAIN_MFG0] = {
-               .name = "mfg0",
-               .sta_mask = BIT(2),
-               .ctl_offs = 0x0308,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .caps = MTK_SCPD_DOMAIN_SUPPLY,
-       },
-       [MT8192_POWER_DOMAIN_MFG1] = {
-               .name = "mfg1",
-               .sta_mask = BIT(3),
-               .ctl_offs = 0x030c,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_1_MFG1,
-                                   MT8192_TOP_AXI_PROT_EN_1_SET,
-                                   MT8192_TOP_AXI_PROT_EN_1_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_1_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_MFG1,
-                                   MT8192_TOP_AXI_PROT_EN_2_SET,
-                                   MT8192_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_2_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MFG1,
-                                   MT8192_TOP_AXI_PROT_EN_SET,
-                                   MT8192_TOP_AXI_PROT_EN_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_MFG1_2ND,
-                                   MT8192_TOP_AXI_PROT_EN_2_SET,
-                                   MT8192_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_2_STA1),
-               },
-               .caps = MTK_SCPD_DOMAIN_SUPPLY,
-       },
-       [MT8192_POWER_DOMAIN_MFG2] = {
-               .name = "mfg2",
-               .sta_mask = BIT(4),
-               .ctl_offs = 0x0310,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-       },
-       [MT8192_POWER_DOMAIN_MFG3] = {
-               .name = "mfg3",
-               .sta_mask = BIT(5),
-               .ctl_offs = 0x0314,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-       },
-       [MT8192_POWER_DOMAIN_MFG4] = {
-               .name = "mfg4",
-               .sta_mask = BIT(6),
-               .ctl_offs = 0x0318,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-       },
-       [MT8192_POWER_DOMAIN_MFG5] = {
-               .name = "mfg5",
-               .sta_mask = BIT(7),
-               .ctl_offs = 0x031c,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-       },
-       [MT8192_POWER_DOMAIN_MFG6] = {
-               .name = "mfg6",
-               .sta_mask = BIT(8),
-               .ctl_offs = 0x0320,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-       },
-       [MT8192_POWER_DOMAIN_DISP] = {
-               .name = "disp",
-               .sta_mask = BIT(20),
-               .ctl_offs = 0x0350,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR_IGN(MT8192_TOP_AXI_PROT_EN_MM_DISP,
-                                       MT8192_TOP_AXI_PROT_EN_MM_SET,
-                                       MT8192_TOP_AXI_PROT_EN_MM_CLR,
-                                       MT8192_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR_IGN(MT8192_TOP_AXI_PROT_EN_MM_2_DISP,
-                                       MT8192_TOP_AXI_PROT_EN_MM_2_SET,
-                                       MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
-                                       MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_DISP,
-                                   MT8192_TOP_AXI_PROT_EN_SET,
-                                   MT8192_TOP_AXI_PROT_EN_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_DISP_2ND,
-                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_DISP_2ND,
-                                   MT8192_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
-               },
-       },
-       [MT8192_POWER_DOMAIN_IPE] = {
-               .name = "ipe",
-               .sta_mask = BIT(14),
-               .ctl_offs = 0x0338,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_IPE,
-                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_IPE_2ND,
-                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
-               },
-       },
-       [MT8192_POWER_DOMAIN_ISP] = {
-               .name = "isp",
-               .sta_mask = BIT(12),
-               .ctl_offs = 0x0330,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_ISP,
-                                   MT8192_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_ISP_2ND,
-                                   MT8192_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
-               },
-       },
-       [MT8192_POWER_DOMAIN_ISP2] = {
-               .name = "isp2",
-               .sta_mask = BIT(13),
-               .ctl_offs = 0x0334,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_ISP2,
-                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_ISP2_2ND,
-                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
-               },
-       },
-       [MT8192_POWER_DOMAIN_MDP] = {
-               .name = "mdp",
-               .sta_mask = BIT(19),
-               .ctl_offs = 0x034c,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_MDP,
-                                   MT8192_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_MDP_2ND,
-                                   MT8192_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
-               },
-       },
-       [MT8192_POWER_DOMAIN_VENC] = {
-               .name = "venc",
-               .sta_mask = BIT(17),
-               .ctl_offs = 0x0344,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VENC,
-                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VENC_2ND,
-                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
-               },
-       },
-       [MT8192_POWER_DOMAIN_VDEC] = {
-               .name = "vdec",
-               .sta_mask = BIT(15),
-               .ctl_offs = 0x033c,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VDEC,
-                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VDEC_2ND,
-                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
-               },
-       },
-       [MT8192_POWER_DOMAIN_VDEC2] = {
-               .name = "vdec2",
-               .sta_mask = BIT(16),
-               .ctl_offs = 0x0340,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-       },
-       [MT8192_POWER_DOMAIN_CAM] = {
-               .name = "cam",
-               .sta_mask = BIT(23),
-               .ctl_offs = 0x035c,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_CAM,
-                                   MT8192_TOP_AXI_PROT_EN_2_SET,
-                                   MT8192_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_2_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_CAM,
-                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_1_CAM,
-                                   MT8192_TOP_AXI_PROT_EN_1_SET,
-                                   MT8192_TOP_AXI_PROT_EN_1_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_1_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_CAM_2ND,
-                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_VDNR_CAM,
-                                   MT8192_TOP_AXI_PROT_EN_VDNR_SET,
-                                   MT8192_TOP_AXI_PROT_EN_VDNR_CLR,
-                                   MT8192_TOP_AXI_PROT_EN_VDNR_STA1),
-               },
-       },
-       [MT8192_POWER_DOMAIN_CAM_RAWA] = {
-               .name = "cam_rawa",
-               .sta_mask = BIT(24),
-               .ctl_offs = 0x0360,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-       },
-       [MT8192_POWER_DOMAIN_CAM_RAWB] = {
-               .name = "cam_rawb",
-               .sta_mask = BIT(25),
-               .ctl_offs = 0x0364,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-       },
-       [MT8192_POWER_DOMAIN_CAM_RAWC] = {
-               .name = "cam_rawc",
-               .sta_mask = BIT(26),
-               .ctl_offs = 0x0368,
-               .pwr_sta_offs = 0x016c,
-               .pwr_sta2nd_offs = 0x0170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-       },
-};
-
-static const struct scpsys_soc_data mt8192_scpsys_data = {
-       .domains_data = scpsys_domain_data_mt8192,
-       .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8192),
-};
-
-#endif /* __SOC_MEDIATEK_MT8192_PM_DOMAINS_H */
diff --git a/drivers/genpd/mediatek/mt8195-pm-domains.h b/drivers/genpd/mediatek/mt8195-pm-domains.h
deleted file mode 100644 (file)
index d7387ea..0000000
+++ /dev/null
@@ -1,613 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2021 MediaTek Inc.
- * Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
- */
-
-#ifndef __SOC_MEDIATEK_MT8195_PM_DOMAINS_H
-#define __SOC_MEDIATEK_MT8195_PM_DOMAINS_H
-
-#include "mtk-pm-domains.h"
-#include <dt-bindings/power/mt8195-power.h>
-
-/*
- * MT8195 power domain support
- */
-
-static const struct scpsys_domain_data scpsys_domain_data_mt8195[] = {
-       [MT8195_POWER_DOMAIN_PCIE_MAC_P0] = {
-               .name = "pcie_mac_p0",
-               .sta_mask = BIT(11),
-               .ctl_offs = 0x328,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_PCIE_MAC_P0,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_SET,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_1_PCIE_MAC_P0,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_SET,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1),
-               },
-       },
-       [MT8195_POWER_DOMAIN_PCIE_MAC_P1] = {
-               .name = "pcie_mac_p1",
-               .sta_mask = BIT(12),
-               .ctl_offs = 0x32C,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_PCIE_MAC_P1,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_SET,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_1_PCIE_MAC_P1,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_SET,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1),
-               },
-       },
-       [MT8195_POWER_DOMAIN_PCIE_PHY] = {
-               .name = "pcie_phy",
-               .sta_mask = BIT(13),
-               .ctl_offs = 0x330,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT8195_POWER_DOMAIN_SSUSB_PCIE_PHY] = {
-               .name = "ssusb_pcie_phy",
-               .sta_mask = BIT(14),
-               .ctl_offs = 0x334,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .caps = MTK_SCPD_ACTIVE_WAKEUP | MTK_SCPD_ALWAYS_ON,
-       },
-       [MT8195_POWER_DOMAIN_CSI_RX_TOP] = {
-               .name = "csi_rx_top",
-               .sta_mask = BIT(18),
-               .ctl_offs = 0x3C4,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_ETHER] = {
-               .name = "ether",
-               .sta_mask = BIT(3),
-               .ctl_offs = 0x344,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT8195_POWER_DOMAIN_ADSP] = {
-               .name = "adsp",
-               .sta_mask = BIT(10),
-               .ctl_offs = 0x360,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_ADSP,
-                                   MT8195_TOP_AXI_PROT_EN_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_2_STA1),
-               },
-               .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT8195_POWER_DOMAIN_AUDIO] = {
-               .name = "audio",
-               .sta_mask = BIT(8),
-               .ctl_offs = 0x358,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_AUDIO,
-                                   MT8195_TOP_AXI_PROT_EN_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_2_STA1),
-               },
-       },
-       [MT8195_POWER_DOMAIN_MFG0] = {
-               .name = "mfg0",
-               .sta_mask = BIT(1),
-               .ctl_offs = 0x300,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
-       },
-       [MT8195_POWER_DOMAIN_MFG1] = {
-               .name = "mfg1",
-               .sta_mask = BIT(2),
-               .ctl_offs = 0x304,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MFG1,
-                                   MT8195_TOP_AXI_PROT_EN_SET,
-                                   MT8195_TOP_AXI_PROT_EN_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_MFG1,
-                                   MT8195_TOP_AXI_PROT_EN_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_2_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_1_MFG1,
-                                   MT8195_TOP_AXI_PROT_EN_1_SET,
-                                   MT8195_TOP_AXI_PROT_EN_1_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_1_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_MFG1_2ND,
-                                   MT8195_TOP_AXI_PROT_EN_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_2_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MFG1_2ND,
-                                   MT8195_TOP_AXI_PROT_EN_SET,
-                                   MT8195_TOP_AXI_PROT_EN_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MFG1,
-                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
-                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
-       },
-       [MT8195_POWER_DOMAIN_MFG2] = {
-               .name = "mfg2",
-               .sta_mask = BIT(3),
-               .ctl_offs = 0x308,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_MFG3] = {
-               .name = "mfg3",
-               .sta_mask = BIT(4),
-               .ctl_offs = 0x30C,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_MFG4] = {
-               .name = "mfg4",
-               .sta_mask = BIT(5),
-               .ctl_offs = 0x310,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_MFG5] = {
-               .name = "mfg5",
-               .sta_mask = BIT(6),
-               .ctl_offs = 0x314,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_MFG6] = {
-               .name = "mfg6",
-               .sta_mask = BIT(7),
-               .ctl_offs = 0x318,
-               .pwr_sta_offs = 0x174,
-               .pwr_sta2nd_offs = 0x178,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_VPPSYS0] = {
-               .name = "vppsys0",
-               .sta_mask = BIT(11),
-               .ctl_offs = 0x364,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VPPSYS0,
-                                   MT8195_TOP_AXI_PROT_EN_SET,
-                                   MT8195_TOP_AXI_PROT_EN_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS0,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VPPSYS0_2ND,
-                                   MT8195_TOP_AXI_PROT_EN_SET,
-                                   MT8195_TOP_AXI_PROT_EN_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS0_2ND,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VPPSYS0,
-                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
-                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1),
-               },
-       },
-       [MT8195_POWER_DOMAIN_VDOSYS0] = {
-               .name = "vdosys0",
-               .sta_mask = BIT(13),
-               .ctl_offs = 0x36C,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDOSYS0,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDOSYS0,
-                                   MT8195_TOP_AXI_PROT_EN_SET,
-                                   MT8195_TOP_AXI_PROT_EN_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VDOSYS0,
-                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
-                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1),
-               },
-       },
-       [MT8195_POWER_DOMAIN_VPPSYS1] = {
-               .name = "vppsys1",
-               .sta_mask = BIT(12),
-               .ctl_offs = 0x368,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VPPSYS1,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VPPSYS1_2ND,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS1,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
-               },
-       },
-       [MT8195_POWER_DOMAIN_VDOSYS1] = {
-               .name = "vdosys1",
-               .sta_mask = BIT(14),
-               .ctl_offs = 0x370,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDOSYS1,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDOSYS1_2ND,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDOSYS1,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
-               },
-       },
-       [MT8195_POWER_DOMAIN_DP_TX] = {
-               .name = "dp_tx",
-               .sta_mask = BIT(16),
-               .ctl_offs = 0x378,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_1_DP_TX,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_SET,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_EPD_TX] = {
-               .name = "epd_tx",
-               .sta_mask = BIT(17),
-               .ctl_offs = 0x37C,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_1_EPD_TX,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_SET,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_HDMI_TX] = {
-               .name = "hdmi_tx",
-               .sta_mask = BIT(18),
-               .ctl_offs = 0x380,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT8195_POWER_DOMAIN_WPESYS] = {
-               .name = "wpesys",
-               .sta_mask = BIT(15),
-               .ctl_offs = 0x374,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_WPESYS,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_WPESYS,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_WPESYS_2ND,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
-               },
-       },
-       [MT8195_POWER_DOMAIN_VDEC0] = {
-               .name = "vdec0",
-               .sta_mask = BIT(20),
-               .ctl_offs = 0x388,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDEC0,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDEC0,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDEC0_2ND,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDEC0_2ND,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_VDEC1] = {
-               .name = "vdec1",
-               .sta_mask = BIT(21),
-               .ctl_offs = 0x38C,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDEC1,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDEC1_2ND,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_VDEC2] = {
-               .name = "vdec2",
-               .sta_mask = BIT(22),
-               .ctl_offs = 0x390,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDEC2,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDEC2_2ND,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_VENC] = {
-               .name = "venc",
-               .sta_mask = BIT(23),
-               .ctl_offs = 0x394,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VENC,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VENC_2ND,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VENC,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_VENC_CORE1] = {
-               .name = "venc_core1",
-               .sta_mask = BIT(24),
-               .ctl_offs = 0x398,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VENC_CORE1,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VENC_CORE1,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_IMG] = {
-               .name = "img",
-               .sta_mask = BIT(29),
-               .ctl_offs = 0x3AC,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_IMG,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_IMG_2ND,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_DIP] = {
-               .name = "dip",
-               .sta_mask = BIT(30),
-               .ctl_offs = 0x3B0,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_IPE] = {
-               .name = "ipe",
-               .sta_mask = BIT(31),
-               .ctl_offs = 0x3B4,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_IPE,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_IPE,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_CAM] = {
-               .name = "cam",
-               .sta_mask = BIT(25),
-               .ctl_offs = 0x39C,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .bp_infracfg = {
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_CAM,
-                                   MT8195_TOP_AXI_PROT_EN_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_2_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_CAM,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_1_CAM,
-                                   MT8195_TOP_AXI_PROT_EN_1_SET,
-                                   MT8195_TOP_AXI_PROT_EN_1_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_1_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_CAM_2ND,
-                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
-                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_CAM,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
-                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
-               },
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_CAM_RAWA] = {
-               .name = "cam_rawa",
-               .sta_mask = BIT(26),
-               .ctl_offs = 0x3A0,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_CAM_RAWB] = {
-               .name = "cam_rawb",
-               .sta_mask = BIT(27),
-               .ctl_offs = 0x3A4,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-       [MT8195_POWER_DOMAIN_CAM_MRAW] = {
-               .name = "cam_mraw",
-               .sta_mask = BIT(28),
-               .ctl_offs = 0x3A8,
-               .pwr_sta_offs = 0x16c,
-               .pwr_sta2nd_offs = 0x170,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
-       },
-};
-
-static const struct scpsys_soc_data mt8195_scpsys_data = {
-       .domains_data = scpsys_domain_data_mt8195,
-       .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8195),
-};
-
-#endif /* __SOC_MEDIATEK_MT8195_PM_DOMAINS_H */
diff --git a/drivers/genpd/mediatek/mtk-pm-domains.c b/drivers/genpd/mediatek/mtk-pm-domains.c
deleted file mode 100644 (file)
index ee96280..0000000
+++ /dev/null
@@ -1,688 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2020 Collabora Ltd.
- */
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/mfd/syscon.h>
-#include <linux/of.h>
-#include <linux/of_clk.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/regmap.h>
-#include <linux/regulator/consumer.h>
-#include <linux/soc/mediatek/infracfg.h>
-
-#include "mt6795-pm-domains.h"
-#include "mt8167-pm-domains.h"
-#include "mt8173-pm-domains.h"
-#include "mt8183-pm-domains.h"
-#include "mt8186-pm-domains.h"
-#include "mt8188-pm-domains.h"
-#include "mt8192-pm-domains.h"
-#include "mt8195-pm-domains.h"
-
-#define MTK_POLL_DELAY_US              10
-#define MTK_POLL_TIMEOUT               USEC_PER_SEC
-
-#define PWR_RST_B_BIT                  BIT(0)
-#define PWR_ISO_BIT                    BIT(1)
-#define PWR_ON_BIT                     BIT(2)
-#define PWR_ON_2ND_BIT                 BIT(3)
-#define PWR_CLK_DIS_BIT                        BIT(4)
-#define PWR_SRAM_CLKISO_BIT            BIT(5)
-#define PWR_SRAM_ISOINT_B_BIT          BIT(6)
-
-struct scpsys_domain {
-       struct generic_pm_domain genpd;
-       const struct scpsys_domain_data *data;
-       struct scpsys *scpsys;
-       int num_clks;
-       struct clk_bulk_data *clks;
-       int num_subsys_clks;
-       struct clk_bulk_data *subsys_clks;
-       struct regmap *infracfg;
-       struct regmap *smi;
-       struct regulator *supply;
-};
-
-struct scpsys {
-       struct device *dev;
-       struct regmap *base;
-       const struct scpsys_soc_data *soc_data;
-       struct genpd_onecell_data pd_data;
-       struct generic_pm_domain *domains[];
-};
-
-#define to_scpsys_domain(gpd) container_of(gpd, struct scpsys_domain, genpd)
-
-static bool scpsys_domain_is_on(struct scpsys_domain *pd)
-{
-       struct scpsys *scpsys = pd->scpsys;
-       u32 status, status2;
-
-       regmap_read(scpsys->base, pd->data->pwr_sta_offs, &status);
-       status &= pd->data->sta_mask;
-
-       regmap_read(scpsys->base, pd->data->pwr_sta2nd_offs, &status2);
-       status2 &= pd->data->sta_mask;
-
-       /* A domain is on when both status bits are set. */
-       return status && status2;
-}
-
-static int scpsys_sram_enable(struct scpsys_domain *pd)
-{
-       u32 pdn_ack = pd->data->sram_pdn_ack_bits;
-       struct scpsys *scpsys = pd->scpsys;
-       unsigned int tmp;
-       int ret;
-
-       regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
-
-       /* Either wait until SRAM_PDN_ACK all 1 or 0 */
-       ret = regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
-                                      (tmp & pdn_ack) == 0, MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
-       if (ret < 0)
-               return ret;
-
-       if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_ISO)) {
-               regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
-               udelay(1);
-               regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT);
-       }
-
-       return 0;
-}
-
-static int scpsys_sram_disable(struct scpsys_domain *pd)
-{
-       u32 pdn_ack = pd->data->sram_pdn_ack_bits;
-       struct scpsys *scpsys = pd->scpsys;
-       unsigned int tmp;
-
-       if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_ISO)) {
-               regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT);
-               udelay(1);
-               regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
-       }
-
-       regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
-
-       /* Either wait until SRAM_PDN_ACK all 1 or 0 */
-       return regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
-                                       (tmp & pdn_ack) == pdn_ack, MTK_POLL_DELAY_US,
-                                       MTK_POLL_TIMEOUT);
-}
-
-static int _scpsys_bus_protect_enable(const struct scpsys_bus_prot_data *bpd, struct regmap *regmap)
-{
-       int i, ret;
-
-       for (i = 0; i < SPM_MAX_BUS_PROT_DATA; i++) {
-               u32 val, mask = bpd[i].bus_prot_mask;
-
-               if (!mask)
-                       break;
-
-               if (bpd[i].bus_prot_reg_update)
-                       regmap_set_bits(regmap, bpd[i].bus_prot_set, mask);
-               else
-                       regmap_write(regmap, bpd[i].bus_prot_set, mask);
-
-               ret = regmap_read_poll_timeout(regmap, bpd[i].bus_prot_sta,
-                                              val, (val & mask) == mask,
-                                              MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static int scpsys_bus_protect_enable(struct scpsys_domain *pd)
-{
-       int ret;
-
-       ret = _scpsys_bus_protect_enable(pd->data->bp_infracfg, pd->infracfg);
-       if (ret)
-               return ret;
-
-       return _scpsys_bus_protect_enable(pd->data->bp_smi, pd->smi);
-}
-
-static int _scpsys_bus_protect_disable(const struct scpsys_bus_prot_data *bpd,
-                                      struct regmap *regmap)
-{
-       int i, ret;
-
-       for (i = SPM_MAX_BUS_PROT_DATA - 1; i >= 0; i--) {
-               u32 val, mask = bpd[i].bus_prot_mask;
-
-               if (!mask)
-                       continue;
-
-               if (bpd[i].bus_prot_reg_update)
-                       regmap_clear_bits(regmap, bpd[i].bus_prot_clr, mask);
-               else
-                       regmap_write(regmap, bpd[i].bus_prot_clr, mask);
-
-               if (bpd[i].ignore_clr_ack)
-                       continue;
-
-               ret = regmap_read_poll_timeout(regmap, bpd[i].bus_prot_sta,
-                                              val, !(val & mask),
-                                              MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static int scpsys_bus_protect_disable(struct scpsys_domain *pd)
-{
-       int ret;
-
-       ret = _scpsys_bus_protect_disable(pd->data->bp_smi, pd->smi);
-       if (ret)
-               return ret;
-
-       return _scpsys_bus_protect_disable(pd->data->bp_infracfg, pd->infracfg);
-}
-
-static int scpsys_regulator_enable(struct regulator *supply)
-{
-       return supply ? regulator_enable(supply) : 0;
-}
-
-static int scpsys_regulator_disable(struct regulator *supply)
-{
-       return supply ? regulator_disable(supply) : 0;
-}
-
-static int scpsys_power_on(struct generic_pm_domain *genpd)
-{
-       struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
-       struct scpsys *scpsys = pd->scpsys;
-       bool tmp;
-       int ret;
-
-       ret = scpsys_regulator_enable(pd->supply);
-       if (ret)
-               return ret;
-
-       ret = clk_bulk_prepare_enable(pd->num_clks, pd->clks);
-       if (ret)
-               goto err_reg;
-
-       if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO))
-               regmap_clear_bits(scpsys->base, pd->data->ext_buck_iso_offs,
-                                 pd->data->ext_buck_iso_mask);
-
-       /* subsys power on */
-       regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
-       regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
-
-       /* wait until PWR_ACK = 1 */
-       ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, tmp, MTK_POLL_DELAY_US,
-                                MTK_POLL_TIMEOUT);
-       if (ret < 0)
-               goto err_pwr_ack;
-
-       regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
-       regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
-       regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
-
-       ret = clk_bulk_prepare_enable(pd->num_subsys_clks, pd->subsys_clks);
-       if (ret)
-               goto err_pwr_ack;
-
-       ret = scpsys_sram_enable(pd);
-       if (ret < 0)
-               goto err_disable_subsys_clks;
-
-       ret = scpsys_bus_protect_disable(pd);
-       if (ret < 0)
-               goto err_disable_sram;
-
-       return 0;
-
-err_disable_sram:
-       scpsys_sram_disable(pd);
-err_disable_subsys_clks:
-       clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks);
-err_pwr_ack:
-       clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
-err_reg:
-       scpsys_regulator_disable(pd->supply);
-       return ret;
-}
-
-static int scpsys_power_off(struct generic_pm_domain *genpd)
-{
-       struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
-       struct scpsys *scpsys = pd->scpsys;
-       bool tmp;
-       int ret;
-
-       ret = scpsys_bus_protect_enable(pd);
-       if (ret < 0)
-               return ret;
-
-       ret = scpsys_sram_disable(pd);
-       if (ret < 0)
-               return ret;
-
-       if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO))
-               regmap_set_bits(scpsys->base, pd->data->ext_buck_iso_offs,
-                               pd->data->ext_buck_iso_mask);
-
-       clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks);
-
-       /* subsys power off */
-       regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
-       regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
-       regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
-       regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
-       regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
-
-       /* wait until PWR_ACK = 0 */
-       ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, !tmp, MTK_POLL_DELAY_US,
-                                MTK_POLL_TIMEOUT);
-       if (ret < 0)
-               return ret;
-
-       clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
-
-       scpsys_regulator_disable(pd->supply);
-
-       return 0;
-}
-
-static struct
-generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_node *node)
-{
-       const struct scpsys_domain_data *domain_data;
-       struct scpsys_domain *pd;
-       struct device_node *root_node = scpsys->dev->of_node;
-       struct device_node *smi_node;
-       struct property *prop;
-       const char *clk_name;
-       int i, ret, num_clks;
-       struct clk *clk;
-       int clk_ind = 0;
-       u32 id;
-
-       ret = of_property_read_u32(node, "reg", &id);
-       if (ret) {
-               dev_err(scpsys->dev, "%pOF: failed to retrieve domain id from reg: %d\n",
-                       node, ret);
-               return ERR_PTR(-EINVAL);
-       }
-
-       if (id >= scpsys->soc_data->num_domains) {
-               dev_err(scpsys->dev, "%pOF: invalid domain id %d\n", node, id);
-               return ERR_PTR(-EINVAL);
-       }
-
-       domain_data = &scpsys->soc_data->domains_data[id];
-       if (domain_data->sta_mask == 0) {
-               dev_err(scpsys->dev, "%pOF: undefined domain id %d\n", node, id);
-               return ERR_PTR(-EINVAL);
-       }
-
-       pd = devm_kzalloc(scpsys->dev, sizeof(*pd), GFP_KERNEL);
-       if (!pd)
-               return ERR_PTR(-ENOMEM);
-
-       pd->data = domain_data;
-       pd->scpsys = scpsys;
-
-       if (MTK_SCPD_CAPS(pd, MTK_SCPD_DOMAIN_SUPPLY)) {
-               /*
-                * Find regulator in current power domain node.
-                * devm_regulator_get() finds regulator in a node and its child
-                * node, so set of_node to current power domain node then change
-                * back to original node after regulator is found for current
-                * power domain node.
-                */
-               scpsys->dev->of_node = node;
-               pd->supply = devm_regulator_get(scpsys->dev, "domain");
-               scpsys->dev->of_node = root_node;
-               if (IS_ERR(pd->supply)) {
-                       dev_err_probe(scpsys->dev, PTR_ERR(pd->supply),
-                                     "%pOF: failed to get power supply.\n",
-                                     node);
-                       return ERR_CAST(pd->supply);
-               }
-       }
-
-       pd->infracfg = syscon_regmap_lookup_by_phandle_optional(node, "mediatek,infracfg");
-       if (IS_ERR(pd->infracfg))
-               return ERR_CAST(pd->infracfg);
-
-       smi_node = of_parse_phandle(node, "mediatek,smi", 0);
-       if (smi_node) {
-               pd->smi = device_node_to_regmap(smi_node);
-               of_node_put(smi_node);
-               if (IS_ERR(pd->smi))
-                       return ERR_CAST(pd->smi);
-       }
-
-       num_clks = of_clk_get_parent_count(node);
-       if (num_clks > 0) {
-               /* Calculate number of subsys_clks */
-               of_property_for_each_string(node, "clock-names", prop, clk_name) {
-                       char *subsys;
-
-                       subsys = strchr(clk_name, '-');
-                       if (subsys)
-                               pd->num_subsys_clks++;
-                       else
-                               pd->num_clks++;
-               }
-
-               pd->clks = devm_kcalloc(scpsys->dev, pd->num_clks, sizeof(*pd->clks), GFP_KERNEL);
-               if (!pd->clks)
-                       return ERR_PTR(-ENOMEM);
-
-               pd->subsys_clks = devm_kcalloc(scpsys->dev, pd->num_subsys_clks,
-                                              sizeof(*pd->subsys_clks), GFP_KERNEL);
-               if (!pd->subsys_clks)
-                       return ERR_PTR(-ENOMEM);
-
-       }
-
-       for (i = 0; i < pd->num_clks; i++) {
-               clk = of_clk_get(node, i);
-               if (IS_ERR(clk)) {
-                       ret = PTR_ERR(clk);
-                       dev_err_probe(scpsys->dev, ret,
-                                     "%pOF: failed to get clk at index %d\n", node, i);
-                       goto err_put_clocks;
-               }
-
-               pd->clks[clk_ind++].clk = clk;
-       }
-
-       for (i = 0; i < pd->num_subsys_clks; i++) {
-               clk = of_clk_get(node, i + clk_ind);
-               if (IS_ERR(clk)) {
-                       ret = PTR_ERR(clk);
-                       dev_err_probe(scpsys->dev, ret,
-                                     "%pOF: failed to get clk at index %d\n", node,
-                                     i + clk_ind);
-                       goto err_put_subsys_clocks;
-               }
-
-               pd->subsys_clks[i].clk = clk;
-       }
-
-       /*
-        * Initially turn on all domains to make the domains usable
-        * with !CONFIG_PM and to get the hardware in sync with the
-        * software.  The unused domains will be switched off during
-        * late_init time.
-        */
-       if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF)) {
-               if (scpsys_domain_is_on(pd))
-                       dev_warn(scpsys->dev,
-                                "%pOF: A default off power domain has been ON\n", node);
-       } else {
-               ret = scpsys_power_on(&pd->genpd);
-               if (ret < 0) {
-                       dev_err(scpsys->dev, "%pOF: failed to power on domain: %d\n", node, ret);
-                       goto err_put_subsys_clocks;
-               }
-
-               if (MTK_SCPD_CAPS(pd, MTK_SCPD_ALWAYS_ON))
-                       pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
-       }
-
-       if (scpsys->domains[id]) {
-               ret = -EINVAL;
-               dev_err(scpsys->dev,
-                       "power domain with id %d already exists, check your device-tree\n", id);
-               goto err_put_subsys_clocks;
-       }
-
-       if (!pd->data->name)
-               pd->genpd.name = node->name;
-       else
-               pd->genpd.name = pd->data->name;
-
-       pd->genpd.power_off = scpsys_power_off;
-       pd->genpd.power_on = scpsys_power_on;
-
-       if (MTK_SCPD_CAPS(pd, MTK_SCPD_ACTIVE_WAKEUP))
-               pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
-
-       if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF))
-               pm_genpd_init(&pd->genpd, NULL, true);
-       else
-               pm_genpd_init(&pd->genpd, NULL, false);
-
-       scpsys->domains[id] = &pd->genpd;
-
-       return scpsys->pd_data.domains[id];
-
-err_put_subsys_clocks:
-       clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
-err_put_clocks:
-       clk_bulk_put(pd->num_clks, pd->clks);
-       return ERR_PTR(ret);
-}
-
-static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *parent)
-{
-       struct generic_pm_domain *child_pd, *parent_pd;
-       struct device_node *child;
-       int ret;
-
-       for_each_child_of_node(parent, child) {
-               u32 id;
-
-               ret = of_property_read_u32(parent, "reg", &id);
-               if (ret) {
-                       dev_err(scpsys->dev, "%pOF: failed to get parent domain id\n", child);
-                       goto err_put_node;
-               }
-
-               if (!scpsys->pd_data.domains[id]) {
-                       ret = -EINVAL;
-                       dev_err(scpsys->dev, "power domain with id %d does not exist\n", id);
-                       goto err_put_node;
-               }
-
-               parent_pd = scpsys->pd_data.domains[id];
-
-               child_pd = scpsys_add_one_domain(scpsys, child);
-               if (IS_ERR(child_pd)) {
-                       ret = PTR_ERR(child_pd);
-                       dev_err_probe(scpsys->dev, ret, "%pOF: failed to get child domain id\n",
-                                     child);
-                       goto err_put_node;
-               }
-
-               ret = pm_genpd_add_subdomain(parent_pd, child_pd);
-               if (ret) {
-                       dev_err(scpsys->dev, "failed to add %s subdomain to parent %s\n",
-                               child_pd->name, parent_pd->name);
-                       goto err_put_node;
-               } else {
-                       dev_dbg(scpsys->dev, "%s add subdomain: %s\n", parent_pd->name,
-                               child_pd->name);
-               }
-
-               /* recursive call to add all subdomains */
-               ret = scpsys_add_subdomain(scpsys, child);
-               if (ret)
-                       goto err_put_node;
-       }
-
-       return 0;
-
-err_put_node:
-       of_node_put(child);
-       return ret;
-}
-
-static void scpsys_remove_one_domain(struct scpsys_domain *pd)
-{
-       int ret;
-
-       if (scpsys_domain_is_on(pd))
-               scpsys_power_off(&pd->genpd);
-
-       /*
-        * We're in the error cleanup already, so we only complain,
-        * but won't emit another error on top of the original one.
-        */
-       ret = pm_genpd_remove(&pd->genpd);
-       if (ret < 0)
-               dev_err(pd->scpsys->dev,
-                       "failed to remove domain '%s' : %d - state may be inconsistent\n",
-                       pd->genpd.name, ret);
-
-       clk_bulk_put(pd->num_clks, pd->clks);
-       clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
-}
-
-static void scpsys_domain_cleanup(struct scpsys *scpsys)
-{
-       struct generic_pm_domain *genpd;
-       struct scpsys_domain *pd;
-       int i;
-
-       for (i = scpsys->pd_data.num_domains - 1; i >= 0; i--) {
-               genpd = scpsys->pd_data.domains[i];
-               if (genpd) {
-                       pd = to_scpsys_domain(genpd);
-                       scpsys_remove_one_domain(pd);
-               }
-       }
-}
-
-static const struct of_device_id scpsys_of_match[] = {
-       {
-               .compatible = "mediatek,mt6795-power-controller",
-               .data = &mt6795_scpsys_data,
-       },
-       {
-               .compatible = "mediatek,mt8167-power-controller",
-               .data = &mt8167_scpsys_data,
-       },
-       {
-               .compatible = "mediatek,mt8173-power-controller",
-               .data = &mt8173_scpsys_data,
-       },
-       {
-               .compatible = "mediatek,mt8183-power-controller",
-               .data = &mt8183_scpsys_data,
-       },
-       {
-               .compatible = "mediatek,mt8186-power-controller",
-               .data = &mt8186_scpsys_data,
-       },
-       {
-               .compatible = "mediatek,mt8188-power-controller",
-               .data = &mt8188_scpsys_data,
-       },
-       {
-               .compatible = "mediatek,mt8192-power-controller",
-               .data = &mt8192_scpsys_data,
-       },
-       {
-               .compatible = "mediatek,mt8195-power-controller",
-               .data = &mt8195_scpsys_data,
-       },
-       { }
-};
-
-static int scpsys_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       const struct scpsys_soc_data *soc;
-       struct device_node *node;
-       struct device *parent;
-       struct scpsys *scpsys;
-       int ret;
-
-       soc = of_device_get_match_data(&pdev->dev);
-       if (!soc) {
-               dev_err(&pdev->dev, "no power controller data\n");
-               return -EINVAL;
-       }
-
-       scpsys = devm_kzalloc(dev, struct_size(scpsys, domains, soc->num_domains), GFP_KERNEL);
-       if (!scpsys)
-               return -ENOMEM;
-
-       scpsys->dev = dev;
-       scpsys->soc_data = soc;
-
-       scpsys->pd_data.domains = scpsys->domains;
-       scpsys->pd_data.num_domains = soc->num_domains;
-
-       parent = dev->parent;
-       if (!parent) {
-               dev_err(dev, "no parent for syscon devices\n");
-               return -ENODEV;
-       }
-
-       scpsys->base = syscon_node_to_regmap(parent->of_node);
-       if (IS_ERR(scpsys->base)) {
-               dev_err(dev, "no regmap available\n");
-               return PTR_ERR(scpsys->base);
-       }
-
-       ret = -ENODEV;
-       for_each_available_child_of_node(np, node) {
-               struct generic_pm_domain *domain;
-
-               domain = scpsys_add_one_domain(scpsys, node);
-               if (IS_ERR(domain)) {
-                       ret = PTR_ERR(domain);
-                       of_node_put(node);
-                       goto err_cleanup_domains;
-               }
-
-               ret = scpsys_add_subdomain(scpsys, node);
-               if (ret) {
-                       of_node_put(node);
-                       goto err_cleanup_domains;
-               }
-       }
-
-       if (ret) {
-               dev_dbg(dev, "no power domains present\n");
-               return ret;
-       }
-
-       ret = of_genpd_add_provider_onecell(np, &scpsys->pd_data);
-       if (ret) {
-               dev_err(dev, "failed to add provider: %d\n", ret);
-               goto err_cleanup_domains;
-       }
-
-       return 0;
-
-err_cleanup_domains:
-       scpsys_domain_cleanup(scpsys);
-       return ret;
-}
-
-static struct platform_driver scpsys_pm_domain_driver = {
-       .probe = scpsys_probe,
-       .driver = {
-               .name = "mtk-power-controller",
-               .suppress_bind_attrs = true,
-               .of_match_table = scpsys_of_match,
-       },
-};
-builtin_platform_driver(scpsys_pm_domain_driver);
diff --git a/drivers/genpd/mediatek/mtk-pm-domains.h b/drivers/genpd/mediatek/mtk-pm-domains.h
deleted file mode 100644 (file)
index 5ec53ee..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef __SOC_MEDIATEK_MTK_PM_DOMAINS_H
-#define __SOC_MEDIATEK_MTK_PM_DOMAINS_H
-
-#define MTK_SCPD_ACTIVE_WAKEUP         BIT(0)
-#define MTK_SCPD_FWAIT_SRAM            BIT(1)
-#define MTK_SCPD_SRAM_ISO              BIT(2)
-#define MTK_SCPD_KEEP_DEFAULT_OFF      BIT(3)
-#define MTK_SCPD_DOMAIN_SUPPLY         BIT(4)
-/* can't set MTK_SCPD_KEEP_DEFAULT_OFF at the same time */
-#define MTK_SCPD_ALWAYS_ON             BIT(5)
-#define MTK_SCPD_EXT_BUCK_ISO          BIT(6)
-#define MTK_SCPD_CAPS(_scpd, _x)       ((_scpd)->data->caps & (_x))
-
-#define SPM_VDE_PWR_CON                        0x0210
-#define SPM_MFG_PWR_CON                        0x0214
-#define SPM_VEN_PWR_CON                        0x0230
-#define SPM_ISP_PWR_CON                        0x0238
-#define SPM_DIS_PWR_CON                        0x023c
-#define SPM_CONN_PWR_CON               0x0280
-#define SPM_VEN2_PWR_CON               0x0298
-#define SPM_AUDIO_PWR_CON              0x029c
-#define SPM_MFG_2D_PWR_CON             0x02c0
-#define SPM_MFG_ASYNC_PWR_CON          0x02c4
-#define SPM_USB_PWR_CON                        0x02cc
-
-#define SPM_PWR_STATUS                 0x060c
-#define SPM_PWR_STATUS_2ND             0x0610
-
-#define PWR_STATUS_CONN                        BIT(1)
-#define PWR_STATUS_DISP                        BIT(3)
-#define PWR_STATUS_MFG                 BIT(4)
-#define PWR_STATUS_ISP                 BIT(5)
-#define PWR_STATUS_VDEC                        BIT(7)
-#define PWR_STATUS_VENC_LT             BIT(20)
-#define PWR_STATUS_VENC                        BIT(21)
-#define PWR_STATUS_MFG_2D              BIT(22)
-#define PWR_STATUS_MFG_ASYNC           BIT(23)
-#define PWR_STATUS_AUDIO               BIT(24)
-#define PWR_STATUS_USB                 BIT(25)
-
-#define SPM_MAX_BUS_PROT_DATA          6
-
-#define _BUS_PROT(_mask, _set, _clr, _sta, _update, _ignore) { \
-               .bus_prot_mask = (_mask),                       \
-               .bus_prot_set = _set,                           \
-               .bus_prot_clr = _clr,                           \
-               .bus_prot_sta = _sta,                           \
-               .bus_prot_reg_update = _update,                 \
-               .ignore_clr_ack = _ignore,                      \
-       }
-
-#define BUS_PROT_WR(_mask, _set, _clr, _sta)                   \
-               _BUS_PROT(_mask, _set, _clr, _sta, false, false)
-
-#define BUS_PROT_WR_IGN(_mask, _set, _clr, _sta)               \
-               _BUS_PROT(_mask, _set, _clr, _sta, false, true)
-
-#define BUS_PROT_UPDATE(_mask, _set, _clr, _sta)               \
-               _BUS_PROT(_mask, _set, _clr, _sta, true, false)
-
-#define BUS_PROT_UPDATE_TOPAXI(_mask)                          \
-               BUS_PROT_UPDATE(_mask,                          \
-                               INFRA_TOPAXI_PROTECTEN,         \
-                               INFRA_TOPAXI_PROTECTEN,         \
-                               INFRA_TOPAXI_PROTECTSTA1)
-
-struct scpsys_bus_prot_data {
-       u32 bus_prot_mask;
-       u32 bus_prot_set;
-       u32 bus_prot_clr;
-       u32 bus_prot_sta;
-       bool bus_prot_reg_update;
-       bool ignore_clr_ack;
-};
-
-/**
- * struct scpsys_domain_data - scp domain data for power on/off flow
- * @name: The name of the power domain.
- * @sta_mask: The mask for power on/off status bit.
- * @ctl_offs: The offset for main power control register.
- * @sram_pdn_bits: The mask for sram power control bits.
- * @sram_pdn_ack_bits: The mask for sram power control acked bits.
- * @ext_buck_iso_offs: The offset for external buck isolation
- * @ext_buck_iso_mask: The mask for external buck isolation
- * @caps: The flag for active wake-up action.
- * @bp_infracfg: bus protection for infracfg subsystem
- * @bp_smi: bus protection for smi subsystem
- */
-struct scpsys_domain_data {
-       const char *name;
-       u32 sta_mask;
-       int ctl_offs;
-       u32 sram_pdn_bits;
-       u32 sram_pdn_ack_bits;
-       int ext_buck_iso_offs;
-       u32 ext_buck_iso_mask;
-       u8 caps;
-       const struct scpsys_bus_prot_data bp_infracfg[SPM_MAX_BUS_PROT_DATA];
-       const struct scpsys_bus_prot_data bp_smi[SPM_MAX_BUS_PROT_DATA];
-       int pwr_sta_offs;
-       int pwr_sta2nd_offs;
-};
-
-struct scpsys_soc_data {
-       const struct scpsys_domain_data *domains_data;
-       int num_domains;
-};
-
-#endif /* __SOC_MEDIATEK_MTK_PM_DOMAINS_H */
diff --git a/drivers/genpd/mediatek/mtk-scpsys.c b/drivers/genpd/mediatek/mtk-scpsys.c
deleted file mode 100644 (file)
index b374d01..0000000
+++ /dev/null
@@ -1,1147 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
- */
-#include <linux/clk.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/mfd/syscon.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/regulator/consumer.h>
-#include <linux/soc/mediatek/infracfg.h>
-
-#include <dt-bindings/power/mt2701-power.h>
-#include <dt-bindings/power/mt2712-power.h>
-#include <dt-bindings/power/mt6797-power.h>
-#include <dt-bindings/power/mt7622-power.h>
-#include <dt-bindings/power/mt7623a-power.h>
-#include <dt-bindings/power/mt8173-power.h>
-
-#define MTK_POLL_DELAY_US   10
-#define MTK_POLL_TIMEOUT    USEC_PER_SEC
-
-#define MTK_SCPD_ACTIVE_WAKEUP         BIT(0)
-#define MTK_SCPD_FWAIT_SRAM            BIT(1)
-#define MTK_SCPD_CAPS(_scpd, _x)       ((_scpd)->data->caps & (_x))
-
-#define SPM_VDE_PWR_CON                        0x0210
-#define SPM_MFG_PWR_CON                        0x0214
-#define SPM_VEN_PWR_CON                        0x0230
-#define SPM_ISP_PWR_CON                        0x0238
-#define SPM_DIS_PWR_CON                        0x023c
-#define SPM_CONN_PWR_CON               0x0280
-#define SPM_VEN2_PWR_CON               0x0298
-#define SPM_AUDIO_PWR_CON              0x029c  /* MT8173, MT2712 */
-#define SPM_BDP_PWR_CON                        0x029c  /* MT2701 */
-#define SPM_ETH_PWR_CON                        0x02a0
-#define SPM_HIF_PWR_CON                        0x02a4
-#define SPM_IFR_MSC_PWR_CON            0x02a8
-#define SPM_MFG_2D_PWR_CON             0x02c0
-#define SPM_MFG_ASYNC_PWR_CON          0x02c4
-#define SPM_USB_PWR_CON                        0x02cc
-#define SPM_USB2_PWR_CON               0x02d4  /* MT2712 */
-#define SPM_ETHSYS_PWR_CON             0x02e0  /* MT7622 */
-#define SPM_HIF0_PWR_CON               0x02e4  /* MT7622 */
-#define SPM_HIF1_PWR_CON               0x02e8  /* MT7622 */
-#define SPM_WB_PWR_CON                 0x02ec  /* MT7622 */
-
-#define SPM_PWR_STATUS                 0x060c
-#define SPM_PWR_STATUS_2ND             0x0610
-
-#define PWR_RST_B_BIT                  BIT(0)
-#define PWR_ISO_BIT                    BIT(1)
-#define PWR_ON_BIT                     BIT(2)
-#define PWR_ON_2ND_BIT                 BIT(3)
-#define PWR_CLK_DIS_BIT                        BIT(4)
-
-#define PWR_STATUS_CONN                        BIT(1)
-#define PWR_STATUS_DISP                        BIT(3)
-#define PWR_STATUS_MFG                 BIT(4)
-#define PWR_STATUS_ISP                 BIT(5)
-#define PWR_STATUS_VDEC                        BIT(7)
-#define PWR_STATUS_BDP                 BIT(14)
-#define PWR_STATUS_ETH                 BIT(15)
-#define PWR_STATUS_HIF                 BIT(16)
-#define PWR_STATUS_IFR_MSC             BIT(17)
-#define PWR_STATUS_USB2                        BIT(19) /* MT2712 */
-#define PWR_STATUS_VENC_LT             BIT(20)
-#define PWR_STATUS_VENC                        BIT(21)
-#define PWR_STATUS_MFG_2D              BIT(22) /* MT8173 */
-#define PWR_STATUS_MFG_ASYNC           BIT(23) /* MT8173 */
-#define PWR_STATUS_AUDIO               BIT(24) /* MT8173, MT2712 */
-#define PWR_STATUS_USB                 BIT(25) /* MT8173, MT2712 */
-#define PWR_STATUS_ETHSYS              BIT(24) /* MT7622 */
-#define PWR_STATUS_HIF0                        BIT(25) /* MT7622 */
-#define PWR_STATUS_HIF1                        BIT(26) /* MT7622 */
-#define PWR_STATUS_WB                  BIT(27) /* MT7622 */
-
-enum clk_id {
-       CLK_NONE,
-       CLK_MM,
-       CLK_MFG,
-       CLK_VENC,
-       CLK_VENC_LT,
-       CLK_ETHIF,
-       CLK_VDEC,
-       CLK_HIFSEL,
-       CLK_JPGDEC,
-       CLK_AUDIO,
-       CLK_MAX,
-};
-
-static const char * const clk_names[] = {
-       NULL,
-       "mm",
-       "mfg",
-       "venc",
-       "venc_lt",
-       "ethif",
-       "vdec",
-       "hif_sel",
-       "jpgdec",
-       "audio",
-       NULL,
-};
-
-#define MAX_CLKS       3
-
-/**
- * struct scp_domain_data - scp domain data for power on/off flow
- * @name: The domain name.
- * @sta_mask: The mask for power on/off status bit.
- * @ctl_offs: The offset for main power control register.
- * @sram_pdn_bits: The mask for sram power control bits.
- * @sram_pdn_ack_bits: The mask for sram power control acked bits.
- * @bus_prot_mask: The mask for single step bus protection.
- * @clk_id: The basic clocks required by this power domain.
- * @caps: The flag for active wake-up action.
- */
-struct scp_domain_data {
-       const char *name;
-       u32 sta_mask;
-       int ctl_offs;
-       u32 sram_pdn_bits;
-       u32 sram_pdn_ack_bits;
-       u32 bus_prot_mask;
-       enum clk_id clk_id[MAX_CLKS];
-       u8 caps;
-};
-
-struct scp;
-
-struct scp_domain {
-       struct generic_pm_domain genpd;
-       struct scp *scp;
-       struct clk *clk[MAX_CLKS];
-       const struct scp_domain_data *data;
-       struct regulator *supply;
-};
-
-struct scp_ctrl_reg {
-       int pwr_sta_offs;
-       int pwr_sta2nd_offs;
-};
-
-struct scp {
-       struct scp_domain *domains;
-       struct genpd_onecell_data pd_data;
-       struct device *dev;
-       void __iomem *base;
-       struct regmap *infracfg;
-       struct scp_ctrl_reg ctrl_reg;
-       bool bus_prot_reg_update;
-};
-
-struct scp_subdomain {
-       int origin;
-       int subdomain;
-};
-
-struct scp_soc_data {
-       const struct scp_domain_data *domains;
-       int num_domains;
-       const struct scp_subdomain *subdomains;
-       int num_subdomains;
-       const struct scp_ctrl_reg regs;
-       bool bus_prot_reg_update;
-};
-
-static int scpsys_domain_is_on(struct scp_domain *scpd)
-{
-       struct scp *scp = scpd->scp;
-
-       u32 status = readl(scp->base + scp->ctrl_reg.pwr_sta_offs) &
-                                               scpd->data->sta_mask;
-       u32 status2 = readl(scp->base + scp->ctrl_reg.pwr_sta2nd_offs) &
-                                               scpd->data->sta_mask;
-
-       /*
-        * A domain is on when both status bits are set. If only one is set
-        * return an error. This happens while powering up a domain
-        */
-
-       if (status && status2)
-               return true;
-       if (!status && !status2)
-               return false;
-
-       return -EINVAL;
-}
-
-static int scpsys_regulator_enable(struct scp_domain *scpd)
-{
-       if (!scpd->supply)
-               return 0;
-
-       return regulator_enable(scpd->supply);
-}
-
-static int scpsys_regulator_disable(struct scp_domain *scpd)
-{
-       if (!scpd->supply)
-               return 0;
-
-       return regulator_disable(scpd->supply);
-}
-
-static void scpsys_clk_disable(struct clk *clk[], int max_num)
-{
-       int i;
-
-       for (i = max_num - 1; i >= 0; i--)
-               clk_disable_unprepare(clk[i]);
-}
-
-static int scpsys_clk_enable(struct clk *clk[], int max_num)
-{
-       int i, ret = 0;
-
-       for (i = 0; i < max_num && clk[i]; i++) {
-               ret = clk_prepare_enable(clk[i]);
-               if (ret) {
-                       scpsys_clk_disable(clk, i);
-                       break;
-               }
-       }
-
-       return ret;
-}
-
-static int scpsys_sram_enable(struct scp_domain *scpd, void __iomem *ctl_addr)
-{
-       u32 val;
-       u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
-       int tmp;
-
-       val = readl(ctl_addr);
-       val &= ~scpd->data->sram_pdn_bits;
-       writel(val, ctl_addr);
-
-       /* Either wait until SRAM_PDN_ACK all 0 or have a force wait */
-       if (MTK_SCPD_CAPS(scpd, MTK_SCPD_FWAIT_SRAM)) {
-               /*
-                * Currently, MTK_SCPD_FWAIT_SRAM is necessary only for
-                * MT7622_POWER_DOMAIN_WB and thus just a trivial setup
-                * is applied here.
-                */
-               usleep_range(12000, 12100);
-       } else {
-               /* Either wait until SRAM_PDN_ACK all 1 or 0 */
-               int ret = readl_poll_timeout(ctl_addr, tmp,
-                               (tmp & pdn_ack) == 0,
-                               MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr)
-{
-       u32 val;
-       u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
-       int tmp;
-
-       val = readl(ctl_addr);
-       val |= scpd->data->sram_pdn_bits;
-       writel(val, ctl_addr);
-
-       /* Either wait until SRAM_PDN_ACK all 1 or 0 */
-       return readl_poll_timeout(ctl_addr, tmp,
-                       (tmp & pdn_ack) == pdn_ack,
-                       MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
-}
-
-static int scpsys_bus_protect_enable(struct scp_domain *scpd)
-{
-       struct scp *scp = scpd->scp;
-
-       if (!scpd->data->bus_prot_mask)
-               return 0;
-
-       return mtk_infracfg_set_bus_protection(scp->infracfg,
-                       scpd->data->bus_prot_mask,
-                       scp->bus_prot_reg_update);
-}
-
-static int scpsys_bus_protect_disable(struct scp_domain *scpd)
-{
-       struct scp *scp = scpd->scp;
-
-       if (!scpd->data->bus_prot_mask)
-               return 0;
-
-       return mtk_infracfg_clear_bus_protection(scp->infracfg,
-                       scpd->data->bus_prot_mask,
-                       scp->bus_prot_reg_update);
-}
-
-static int scpsys_power_on(struct generic_pm_domain *genpd)
-{
-       struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
-       struct scp *scp = scpd->scp;
-       void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
-       u32 val;
-       int ret, tmp;
-
-       ret = scpsys_regulator_enable(scpd);
-       if (ret < 0)
-               return ret;
-
-       ret = scpsys_clk_enable(scpd->clk, MAX_CLKS);
-       if (ret)
-               goto err_clk;
-
-       /* subsys power on */
-       val = readl(ctl_addr);
-       val |= PWR_ON_BIT;
-       writel(val, ctl_addr);
-       val |= PWR_ON_2ND_BIT;
-       writel(val, ctl_addr);
-
-       /* wait until PWR_ACK = 1 */
-       ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp > 0,
-                                MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
-       if (ret < 0)
-               goto err_pwr_ack;
-
-       val &= ~PWR_CLK_DIS_BIT;
-       writel(val, ctl_addr);
-
-       val &= ~PWR_ISO_BIT;
-       writel(val, ctl_addr);
-
-       val |= PWR_RST_B_BIT;
-       writel(val, ctl_addr);
-
-       ret = scpsys_sram_enable(scpd, ctl_addr);
-       if (ret < 0)
-               goto err_pwr_ack;
-
-       ret = scpsys_bus_protect_disable(scpd);
-       if (ret < 0)
-               goto err_pwr_ack;
-
-       return 0;
-
-err_pwr_ack:
-       scpsys_clk_disable(scpd->clk, MAX_CLKS);
-err_clk:
-       scpsys_regulator_disable(scpd);
-
-       dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
-
-       return ret;
-}
-
-static int scpsys_power_off(struct generic_pm_domain *genpd)
-{
-       struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
-       struct scp *scp = scpd->scp;
-       void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
-       u32 val;
-       int ret, tmp;
-
-       ret = scpsys_bus_protect_enable(scpd);
-       if (ret < 0)
-               goto out;
-
-       ret = scpsys_sram_disable(scpd, ctl_addr);
-       if (ret < 0)
-               goto out;
-
-       /* subsys power off */
-       val = readl(ctl_addr);
-       val |= PWR_ISO_BIT;
-       writel(val, ctl_addr);
-
-       val &= ~PWR_RST_B_BIT;
-       writel(val, ctl_addr);
-
-       val |= PWR_CLK_DIS_BIT;
-       writel(val, ctl_addr);
-
-       val &= ~PWR_ON_BIT;
-       writel(val, ctl_addr);
-
-       val &= ~PWR_ON_2ND_BIT;
-       writel(val, ctl_addr);
-
-       /* wait until PWR_ACK = 0 */
-       ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp == 0,
-                                MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
-       if (ret < 0)
-               goto out;
-
-       scpsys_clk_disable(scpd->clk, MAX_CLKS);
-
-       ret = scpsys_regulator_disable(scpd);
-       if (ret < 0)
-               goto out;
-
-       return 0;
-
-out:
-       dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name);
-
-       return ret;
-}
-
-static void init_clks(struct platform_device *pdev, struct clk **clk)
-{
-       int i;
-
-       for (i = CLK_NONE + 1; i < CLK_MAX; i++)
-               clk[i] = devm_clk_get(&pdev->dev, clk_names[i]);
-}
-
-static struct scp *init_scp(struct platform_device *pdev,
-                       const struct scp_domain_data *scp_domain_data, int num,
-                       const struct scp_ctrl_reg *scp_ctrl_reg,
-                       bool bus_prot_reg_update)
-{
-       struct genpd_onecell_data *pd_data;
-       struct resource *res;
-       int i, j;
-       struct scp *scp;
-       struct clk *clk[CLK_MAX];
-
-       scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL);
-       if (!scp)
-               return ERR_PTR(-ENOMEM);
-
-       scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs;
-       scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs;
-
-       scp->bus_prot_reg_update = bus_prot_reg_update;
-
-       scp->dev = &pdev->dev;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       scp->base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(scp->base))
-               return ERR_CAST(scp->base);
-
-       scp->domains = devm_kcalloc(&pdev->dev,
-                               num, sizeof(*scp->domains), GFP_KERNEL);
-       if (!scp->domains)
-               return ERR_PTR(-ENOMEM);
-
-       pd_data = &scp->pd_data;
-
-       pd_data->domains = devm_kcalloc(&pdev->dev,
-                       num, sizeof(*pd_data->domains), GFP_KERNEL);
-       if (!pd_data->domains)
-               return ERR_PTR(-ENOMEM);
-
-       scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
-                       "infracfg");
-       if (IS_ERR(scp->infracfg)) {
-               dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n",
-                               PTR_ERR(scp->infracfg));
-               return ERR_CAST(scp->infracfg);
-       }
-
-       for (i = 0; i < num; i++) {
-               struct scp_domain *scpd = &scp->domains[i];
-               const struct scp_domain_data *data = &scp_domain_data[i];
-
-               scpd->supply = devm_regulator_get_optional(&pdev->dev, data->name);
-               if (IS_ERR(scpd->supply)) {
-                       if (PTR_ERR(scpd->supply) == -ENODEV)
-                               scpd->supply = NULL;
-                       else
-                               return ERR_CAST(scpd->supply);
-               }
-       }
-
-       pd_data->num_domains = num;
-
-       init_clks(pdev, clk);
-
-       for (i = 0; i < num; i++) {
-               struct scp_domain *scpd = &scp->domains[i];
-               struct generic_pm_domain *genpd = &scpd->genpd;
-               const struct scp_domain_data *data = &scp_domain_data[i];
-
-               pd_data->domains[i] = genpd;
-               scpd->scp = scp;
-
-               scpd->data = data;
-
-               for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) {
-                       struct clk *c = clk[data->clk_id[j]];
-
-                       if (IS_ERR(c)) {
-                               dev_err(&pdev->dev, "%s: clk unavailable\n",
-                                       data->name);
-                               return ERR_CAST(c);
-                       }
-
-                       scpd->clk[j] = c;
-               }
-
-               genpd->name = data->name;
-               genpd->power_off = scpsys_power_off;
-               genpd->power_on = scpsys_power_on;
-               if (MTK_SCPD_CAPS(scpd, MTK_SCPD_ACTIVE_WAKEUP))
-                       genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP;
-       }
-
-       return scp;
-}
-
-static void mtk_register_power_domains(struct platform_device *pdev,
-                               struct scp *scp, int num)
-{
-       struct genpd_onecell_data *pd_data;
-       int i, ret;
-
-       for (i = 0; i < num; i++) {
-               struct scp_domain *scpd = &scp->domains[i];
-               struct generic_pm_domain *genpd = &scpd->genpd;
-               bool on;
-
-               /*
-                * Initially turn on all domains to make the domains usable
-                * with !CONFIG_PM and to get the hardware in sync with the
-                * software.  The unused domains will be switched off during
-                * late_init time.
-                */
-               on = !WARN_ON(genpd->power_on(genpd) < 0);
-
-               pm_genpd_init(genpd, NULL, !on);
-       }
-
-       /*
-        * We are not allowed to fail here since there is no way to unregister
-        * a power domain. Once registered above we have to keep the domains
-        * valid.
-        */
-
-       pd_data = &scp->pd_data;
-
-       ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data);
-       if (ret)
-               dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
-}
-
-/*
- * MT2701 power domain support
- */
-
-static const struct scp_domain_data scp_domain_data_mt2701[] = {
-       [MT2701_POWER_DOMAIN_CONN] = {
-               .name = "conn",
-               .sta_mask = PWR_STATUS_CONN,
-               .ctl_offs = SPM_CONN_PWR_CON,
-               .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M |
-                                MT2701_TOP_AXI_PROT_EN_CONN_S,
-               .clk_id = {CLK_NONE},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2701_POWER_DOMAIN_DISP] = {
-               .name = "disp",
-               .sta_mask = PWR_STATUS_DISP,
-               .ctl_offs = SPM_DIS_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .clk_id = {CLK_MM},
-               .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_MM_M0,
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2701_POWER_DOMAIN_MFG] = {
-               .name = "mfg",
-               .sta_mask = PWR_STATUS_MFG,
-               .ctl_offs = SPM_MFG_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .clk_id = {CLK_MFG},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2701_POWER_DOMAIN_VDEC] = {
-               .name = "vdec",
-               .sta_mask = PWR_STATUS_VDEC,
-               .ctl_offs = SPM_VDE_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .clk_id = {CLK_MM},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2701_POWER_DOMAIN_ISP] = {
-               .name = "isp",
-               .sta_mask = PWR_STATUS_ISP,
-               .ctl_offs = SPM_ISP_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(13, 12),
-               .clk_id = {CLK_MM},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2701_POWER_DOMAIN_BDP] = {
-               .name = "bdp",
-               .sta_mask = PWR_STATUS_BDP,
-               .ctl_offs = SPM_BDP_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .clk_id = {CLK_NONE},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2701_POWER_DOMAIN_ETH] = {
-               .name = "eth",
-               .sta_mask = PWR_STATUS_ETH,
-               .ctl_offs = SPM_ETH_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .clk_id = {CLK_ETHIF},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2701_POWER_DOMAIN_HIF] = {
-               .name = "hif",
-               .sta_mask = PWR_STATUS_HIF,
-               .ctl_offs = SPM_HIF_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .clk_id = {CLK_ETHIF},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2701_POWER_DOMAIN_IFR_MSC] = {
-               .name = "ifr_msc",
-               .sta_mask = PWR_STATUS_IFR_MSC,
-               .ctl_offs = SPM_IFR_MSC_PWR_CON,
-               .clk_id = {CLK_NONE},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-};
-
-/*
- * MT2712 power domain support
- */
-static const struct scp_domain_data scp_domain_data_mt2712[] = {
-       [MT2712_POWER_DOMAIN_MM] = {
-               .name = "mm",
-               .sta_mask = PWR_STATUS_DISP,
-               .ctl_offs = SPM_DIS_PWR_CON,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .clk_id = {CLK_MM},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2712_POWER_DOMAIN_VDEC] = {
-               .name = "vdec",
-               .sta_mask = PWR_STATUS_VDEC,
-               .ctl_offs = SPM_VDE_PWR_CON,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .clk_id = {CLK_MM, CLK_VDEC},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2712_POWER_DOMAIN_VENC] = {
-               .name = "venc",
-               .sta_mask = PWR_STATUS_VENC,
-               .ctl_offs = SPM_VEN_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .clk_id = {CLK_MM, CLK_VENC, CLK_JPGDEC},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2712_POWER_DOMAIN_ISP] = {
-               .name = "isp",
-               .sta_mask = PWR_STATUS_ISP,
-               .ctl_offs = SPM_ISP_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(13, 12),
-               .clk_id = {CLK_MM},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2712_POWER_DOMAIN_AUDIO] = {
-               .name = "audio",
-               .sta_mask = PWR_STATUS_AUDIO,
-               .ctl_offs = SPM_AUDIO_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .clk_id = {CLK_AUDIO},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2712_POWER_DOMAIN_USB] = {
-               .name = "usb",
-               .sta_mask = PWR_STATUS_USB,
-               .ctl_offs = SPM_USB_PWR_CON,
-               .sram_pdn_bits = GENMASK(10, 8),
-               .sram_pdn_ack_bits = GENMASK(14, 12),
-               .clk_id = {CLK_NONE},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2712_POWER_DOMAIN_USB2] = {
-               .name = "usb2",
-               .sta_mask = PWR_STATUS_USB2,
-               .ctl_offs = SPM_USB2_PWR_CON,
-               .sram_pdn_bits = GENMASK(10, 8),
-               .sram_pdn_ack_bits = GENMASK(14, 12),
-               .clk_id = {CLK_NONE},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2712_POWER_DOMAIN_MFG] = {
-               .name = "mfg",
-               .sta_mask = PWR_STATUS_MFG,
-               .ctl_offs = SPM_MFG_PWR_CON,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(16, 16),
-               .clk_id = {CLK_MFG},
-               .bus_prot_mask = BIT(14) | BIT(21) | BIT(23),
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2712_POWER_DOMAIN_MFG_SC1] = {
-               .name = "mfg_sc1",
-               .sta_mask = BIT(22),
-               .ctl_offs = 0x02c0,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(16, 16),
-               .clk_id = {CLK_NONE},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2712_POWER_DOMAIN_MFG_SC2] = {
-               .name = "mfg_sc2",
-               .sta_mask = BIT(23),
-               .ctl_offs = 0x02c4,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(16, 16),
-               .clk_id = {CLK_NONE},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT2712_POWER_DOMAIN_MFG_SC3] = {
-               .name = "mfg_sc3",
-               .sta_mask = BIT(30),
-               .ctl_offs = 0x01f8,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(16, 16),
-               .clk_id = {CLK_NONE},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-};
-
-static const struct scp_subdomain scp_subdomain_mt2712[] = {
-       {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_VDEC},
-       {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_VENC},
-       {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_ISP},
-       {MT2712_POWER_DOMAIN_MFG, MT2712_POWER_DOMAIN_MFG_SC1},
-       {MT2712_POWER_DOMAIN_MFG_SC1, MT2712_POWER_DOMAIN_MFG_SC2},
-       {MT2712_POWER_DOMAIN_MFG_SC2, MT2712_POWER_DOMAIN_MFG_SC3},
-};
-
-/*
- * MT6797 power domain support
- */
-
-static const struct scp_domain_data scp_domain_data_mt6797[] = {
-       [MT6797_POWER_DOMAIN_VDEC] = {
-               .name = "vdec",
-               .sta_mask = BIT(7),
-               .ctl_offs = 0x300,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .clk_id = {CLK_VDEC},
-       },
-       [MT6797_POWER_DOMAIN_VENC] = {
-               .name = "venc",
-               .sta_mask = BIT(21),
-               .ctl_offs = 0x304,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .clk_id = {CLK_NONE},
-       },
-       [MT6797_POWER_DOMAIN_ISP] = {
-               .name = "isp",
-               .sta_mask = BIT(5),
-               .ctl_offs = 0x308,
-               .sram_pdn_bits = GENMASK(9, 8),
-               .sram_pdn_ack_bits = GENMASK(13, 12),
-               .clk_id = {CLK_NONE},
-       },
-       [MT6797_POWER_DOMAIN_MM] = {
-               .name = "mm",
-               .sta_mask = BIT(3),
-               .ctl_offs = 0x30C,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .clk_id = {CLK_MM},
-               .bus_prot_mask = (BIT(1) | BIT(2)),
-       },
-       [MT6797_POWER_DOMAIN_AUDIO] = {
-               .name = "audio",
-               .sta_mask = BIT(24),
-               .ctl_offs = 0x314,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .clk_id = {CLK_NONE},
-       },
-       [MT6797_POWER_DOMAIN_MFG_ASYNC] = {
-               .name = "mfg_async",
-               .sta_mask = BIT(13),
-               .ctl_offs = 0x334,
-               .sram_pdn_bits = 0,
-               .sram_pdn_ack_bits = 0,
-               .clk_id = {CLK_MFG},
-       },
-       [MT6797_POWER_DOMAIN_MJC] = {
-               .name = "mjc",
-               .sta_mask = BIT(20),
-               .ctl_offs = 0x310,
-               .sram_pdn_bits = GENMASK(8, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .clk_id = {CLK_NONE},
-       },
-};
-
-#define SPM_PWR_STATUS_MT6797          0x0180
-#define SPM_PWR_STATUS_2ND_MT6797      0x0184
-
-static const struct scp_subdomain scp_subdomain_mt6797[] = {
-       {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VDEC},
-       {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_ISP},
-       {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VENC},
-       {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_MJC},
-};
-
-/*
- * MT7622 power domain support
- */
-
-static const struct scp_domain_data scp_domain_data_mt7622[] = {
-       [MT7622_POWER_DOMAIN_ETHSYS] = {
-               .name = "ethsys",
-               .sta_mask = PWR_STATUS_ETHSYS,
-               .ctl_offs = SPM_ETHSYS_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .clk_id = {CLK_NONE},
-               .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_ETHSYS,
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT7622_POWER_DOMAIN_HIF0] = {
-               .name = "hif0",
-               .sta_mask = PWR_STATUS_HIF0,
-               .ctl_offs = SPM_HIF0_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .clk_id = {CLK_HIFSEL},
-               .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF0,
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT7622_POWER_DOMAIN_HIF1] = {
-               .name = "hif1",
-               .sta_mask = PWR_STATUS_HIF1,
-               .ctl_offs = SPM_HIF1_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .clk_id = {CLK_HIFSEL},
-               .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF1,
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT7622_POWER_DOMAIN_WB] = {
-               .name = "wb",
-               .sta_mask = PWR_STATUS_WB,
-               .ctl_offs = SPM_WB_PWR_CON,
-               .sram_pdn_bits = 0,
-               .sram_pdn_ack_bits = 0,
-               .clk_id = {CLK_NONE},
-               .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_WB,
-               .caps = MTK_SCPD_ACTIVE_WAKEUP | MTK_SCPD_FWAIT_SRAM,
-       },
-};
-
-/*
- * MT7623A power domain support
- */
-
-static const struct scp_domain_data scp_domain_data_mt7623a[] = {
-       [MT7623A_POWER_DOMAIN_CONN] = {
-               .name = "conn",
-               .sta_mask = PWR_STATUS_CONN,
-               .ctl_offs = SPM_CONN_PWR_CON,
-               .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M |
-                                MT2701_TOP_AXI_PROT_EN_CONN_S,
-               .clk_id = {CLK_NONE},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT7623A_POWER_DOMAIN_ETH] = {
-               .name = "eth",
-               .sta_mask = PWR_STATUS_ETH,
-               .ctl_offs = SPM_ETH_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .clk_id = {CLK_ETHIF},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT7623A_POWER_DOMAIN_HIF] = {
-               .name = "hif",
-               .sta_mask = PWR_STATUS_HIF,
-               .ctl_offs = SPM_HIF_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .clk_id = {CLK_ETHIF},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT7623A_POWER_DOMAIN_IFR_MSC] = {
-               .name = "ifr_msc",
-               .sta_mask = PWR_STATUS_IFR_MSC,
-               .ctl_offs = SPM_IFR_MSC_PWR_CON,
-               .clk_id = {CLK_NONE},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-};
-
-/*
- * MT8173 power domain support
- */
-
-static const struct scp_domain_data scp_domain_data_mt8173[] = {
-       [MT8173_POWER_DOMAIN_VDEC] = {
-               .name = "vdec",
-               .sta_mask = PWR_STATUS_VDEC,
-               .ctl_offs = SPM_VDE_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .clk_id = {CLK_MM},
-       },
-       [MT8173_POWER_DOMAIN_VENC] = {
-               .name = "venc",
-               .sta_mask = PWR_STATUS_VENC,
-               .ctl_offs = SPM_VEN_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .clk_id = {CLK_MM, CLK_VENC},
-       },
-       [MT8173_POWER_DOMAIN_ISP] = {
-               .name = "isp",
-               .sta_mask = PWR_STATUS_ISP,
-               .ctl_offs = SPM_ISP_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(13, 12),
-               .clk_id = {CLK_MM},
-       },
-       [MT8173_POWER_DOMAIN_MM] = {
-               .name = "mm",
-               .sta_mask = PWR_STATUS_DISP,
-               .ctl_offs = SPM_DIS_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(12, 12),
-               .clk_id = {CLK_MM},
-               .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
-                       MT8173_TOP_AXI_PROT_EN_MM_M1,
-       },
-       [MT8173_POWER_DOMAIN_VENC_LT] = {
-               .name = "venc_lt",
-               .sta_mask = PWR_STATUS_VENC_LT,
-               .ctl_offs = SPM_VEN2_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .clk_id = {CLK_MM, CLK_VENC_LT},
-       },
-       [MT8173_POWER_DOMAIN_AUDIO] = {
-               .name = "audio",
-               .sta_mask = PWR_STATUS_AUDIO,
-               .ctl_offs = SPM_AUDIO_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .clk_id = {CLK_NONE},
-       },
-       [MT8173_POWER_DOMAIN_USB] = {
-               .name = "usb",
-               .sta_mask = PWR_STATUS_USB,
-               .ctl_offs = SPM_USB_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(15, 12),
-               .clk_id = {CLK_NONE},
-               .caps = MTK_SCPD_ACTIVE_WAKEUP,
-       },
-       [MT8173_POWER_DOMAIN_MFG_ASYNC] = {
-               .name = "mfg_async",
-               .sta_mask = PWR_STATUS_MFG_ASYNC,
-               .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = 0,
-               .clk_id = {CLK_MFG},
-       },
-       [MT8173_POWER_DOMAIN_MFG_2D] = {
-               .name = "mfg_2d",
-               .sta_mask = PWR_STATUS_MFG_2D,
-               .ctl_offs = SPM_MFG_2D_PWR_CON,
-               .sram_pdn_bits = GENMASK(11, 8),
-               .sram_pdn_ack_bits = GENMASK(13, 12),
-               .clk_id = {CLK_NONE},
-       },
-       [MT8173_POWER_DOMAIN_MFG] = {
-               .name = "mfg",
-               .sta_mask = PWR_STATUS_MFG,
-               .ctl_offs = SPM_MFG_PWR_CON,
-               .sram_pdn_bits = GENMASK(13, 8),
-               .sram_pdn_ack_bits = GENMASK(21, 16),
-               .clk_id = {CLK_NONE},
-               .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
-                       MT8173_TOP_AXI_PROT_EN_MFG_M0 |
-                       MT8173_TOP_AXI_PROT_EN_MFG_M1 |
-                       MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT,
-       },
-};
-
-static const struct scp_subdomain scp_subdomain_mt8173[] = {
-       {MT8173_POWER_DOMAIN_MFG_ASYNC, MT8173_POWER_DOMAIN_MFG_2D},
-       {MT8173_POWER_DOMAIN_MFG_2D, MT8173_POWER_DOMAIN_MFG},
-};
-
-static const struct scp_soc_data mt2701_data = {
-       .domains = scp_domain_data_mt2701,
-       .num_domains = ARRAY_SIZE(scp_domain_data_mt2701),
-       .regs = {
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
-       },
-       .bus_prot_reg_update = true,
-};
-
-static const struct scp_soc_data mt2712_data = {
-       .domains = scp_domain_data_mt2712,
-       .num_domains = ARRAY_SIZE(scp_domain_data_mt2712),
-       .subdomains = scp_subdomain_mt2712,
-       .num_subdomains = ARRAY_SIZE(scp_subdomain_mt2712),
-       .regs = {
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
-       },
-       .bus_prot_reg_update = false,
-};
-
-static const struct scp_soc_data mt6797_data = {
-       .domains = scp_domain_data_mt6797,
-       .num_domains = ARRAY_SIZE(scp_domain_data_mt6797),
-       .subdomains = scp_subdomain_mt6797,
-       .num_subdomains = ARRAY_SIZE(scp_subdomain_mt6797),
-       .regs = {
-               .pwr_sta_offs = SPM_PWR_STATUS_MT6797,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
-       },
-       .bus_prot_reg_update = true,
-};
-
-static const struct scp_soc_data mt7622_data = {
-       .domains = scp_domain_data_mt7622,
-       .num_domains = ARRAY_SIZE(scp_domain_data_mt7622),
-       .regs = {
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
-       },
-       .bus_prot_reg_update = true,
-};
-
-static const struct scp_soc_data mt7623a_data = {
-       .domains = scp_domain_data_mt7623a,
-       .num_domains = ARRAY_SIZE(scp_domain_data_mt7623a),
-       .regs = {
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
-       },
-       .bus_prot_reg_update = true,
-};
-
-static const struct scp_soc_data mt8173_data = {
-       .domains = scp_domain_data_mt8173,
-       .num_domains = ARRAY_SIZE(scp_domain_data_mt8173),
-       .subdomains = scp_subdomain_mt8173,
-       .num_subdomains = ARRAY_SIZE(scp_subdomain_mt8173),
-       .regs = {
-               .pwr_sta_offs = SPM_PWR_STATUS,
-               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
-       },
-       .bus_prot_reg_update = true,
-};
-
-/*
- * scpsys driver init
- */
-
-static const struct of_device_id of_scpsys_match_tbl[] = {
-       {
-               .compatible = "mediatek,mt2701-scpsys",
-               .data = &mt2701_data,
-       }, {
-               .compatible = "mediatek,mt2712-scpsys",
-               .data = &mt2712_data,
-       }, {
-               .compatible = "mediatek,mt6797-scpsys",
-               .data = &mt6797_data,
-       }, {
-               .compatible = "mediatek,mt7622-scpsys",
-               .data = &mt7622_data,
-       }, {
-               .compatible = "mediatek,mt7623a-scpsys",
-               .data = &mt7623a_data,
-       }, {
-               .compatible = "mediatek,mt8173-scpsys",
-               .data = &mt8173_data,
-       }, {
-               /* sentinel */
-       }
-};
-
-static int scpsys_probe(struct platform_device *pdev)
-{
-       const struct scp_subdomain *sd;
-       const struct scp_soc_data *soc;
-       struct scp *scp;
-       struct genpd_onecell_data *pd_data;
-       int i, ret;
-
-       soc = of_device_get_match_data(&pdev->dev);
-
-       scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs,
-                       soc->bus_prot_reg_update);
-       if (IS_ERR(scp))
-               return PTR_ERR(scp);
-
-       mtk_register_power_domains(pdev, scp, soc->num_domains);
-
-       pd_data = &scp->pd_data;
-
-       for (i = 0, sd = soc->subdomains; i < soc->num_subdomains; i++, sd++) {
-               ret = pm_genpd_add_subdomain(pd_data->domains[sd->origin],
-                                            pd_data->domains[sd->subdomain]);
-               if (ret && IS_ENABLED(CONFIG_PM))
-                       dev_err(&pdev->dev, "Failed to add subdomain: %d\n",
-                               ret);
-       }
-
-       return 0;
-}
-
-static struct platform_driver scpsys_drv = {
-       .probe = scpsys_probe,
-       .driver = {
-               .name = "mtk-scpsys",
-               .suppress_bind_attrs = true,
-               .owner = THIS_MODULE,
-               .of_match_table = of_scpsys_match_tbl,
-       },
-};
-builtin_platform_driver(scpsys_drv);
diff --git a/drivers/genpd/qcom/Makefile b/drivers/genpd/qcom/Makefile
deleted file mode 100644 (file)
index 403dfc5..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_QCOM_CPR)         += cpr.o
-obj-$(CONFIG_QCOM_RPMPD)       += rpmpd.o
-obj-$(CONFIG_QCOM_RPMHPD)      += rpmhpd.o
diff --git a/drivers/genpd/qcom/cpr.c b/drivers/genpd/qcom/cpr.c
deleted file mode 100644 (file)
index 94a3f09..0000000
+++ /dev/null
@@ -1,1756 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
- * Copyright (c) 2019, Linaro Limited
- */
-
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/debugfs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/pm_opp.h>
-#include <linux/interrupt.h>
-#include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
-#include <linux/regulator/consumer.h>
-#include <linux/clk.h>
-#include <linux/nvmem-consumer.h>
-
-/* Register Offsets for RB-CPR and Bit Definitions */
-
-/* RBCPR Version Register */
-#define REG_RBCPR_VERSION              0
-#define RBCPR_VER_2                    0x02
-#define FLAGS_IGNORE_1ST_IRQ_STATUS    BIT(0)
-
-/* RBCPR Gate Count and Target Registers */
-#define REG_RBCPR_GCNT_TARGET(n)       (0x60 + 4 * (n))
-
-#define RBCPR_GCNT_TARGET_TARGET_SHIFT 0
-#define RBCPR_GCNT_TARGET_TARGET_MASK  GENMASK(11, 0)
-#define RBCPR_GCNT_TARGET_GCNT_SHIFT   12
-#define RBCPR_GCNT_TARGET_GCNT_MASK    GENMASK(9, 0)
-
-/* RBCPR Timer Control */
-#define REG_RBCPR_TIMER_INTERVAL       0x44
-#define REG_RBIF_TIMER_ADJUST          0x4c
-
-#define RBIF_TIMER_ADJ_CONS_UP_MASK    GENMASK(3, 0)
-#define RBIF_TIMER_ADJ_CONS_UP_SHIFT   0
-#define RBIF_TIMER_ADJ_CONS_DOWN_MASK  GENMASK(3, 0)
-#define RBIF_TIMER_ADJ_CONS_DOWN_SHIFT 4
-#define RBIF_TIMER_ADJ_CLAMP_INT_MASK  GENMASK(7, 0)
-#define RBIF_TIMER_ADJ_CLAMP_INT_SHIFT 8
-
-/* RBCPR Config Register */
-#define REG_RBIF_LIMIT                 0x48
-#define RBIF_LIMIT_CEILING_MASK                GENMASK(5, 0)
-#define RBIF_LIMIT_CEILING_SHIFT       6
-#define RBIF_LIMIT_FLOOR_BITS          6
-#define RBIF_LIMIT_FLOOR_MASK          GENMASK(5, 0)
-
-#define RBIF_LIMIT_CEILING_DEFAULT     RBIF_LIMIT_CEILING_MASK
-#define RBIF_LIMIT_FLOOR_DEFAULT       0
-
-#define REG_RBIF_SW_VLEVEL             0x94
-#define RBIF_SW_VLEVEL_DEFAULT         0x20
-
-#define REG_RBCPR_STEP_QUOT            0x80
-#define RBCPR_STEP_QUOT_STEPQUOT_MASK  GENMASK(7, 0)
-#define RBCPR_STEP_QUOT_IDLE_CLK_MASK  GENMASK(3, 0)
-#define RBCPR_STEP_QUOT_IDLE_CLK_SHIFT 8
-
-/* RBCPR Control Register */
-#define REG_RBCPR_CTL                  0x90
-
-#define RBCPR_CTL_LOOP_EN                      BIT(0)
-#define RBCPR_CTL_TIMER_EN                     BIT(3)
-#define RBCPR_CTL_SW_AUTO_CONT_ACK_EN          BIT(5)
-#define RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN      BIT(6)
-#define RBCPR_CTL_COUNT_MODE                   BIT(10)
-#define RBCPR_CTL_UP_THRESHOLD_MASK    GENMASK(3, 0)
-#define RBCPR_CTL_UP_THRESHOLD_SHIFT   24
-#define RBCPR_CTL_DN_THRESHOLD_MASK    GENMASK(3, 0)
-#define RBCPR_CTL_DN_THRESHOLD_SHIFT   28
-
-/* RBCPR Ack/Nack Response */
-#define REG_RBIF_CONT_ACK_CMD          0x98
-#define REG_RBIF_CONT_NACK_CMD         0x9c
-
-/* RBCPR Result status Register */
-#define REG_RBCPR_RESULT_0             0xa0
-
-#define RBCPR_RESULT0_BUSY_SHIFT       19
-#define RBCPR_RESULT0_BUSY_MASK                BIT(RBCPR_RESULT0_BUSY_SHIFT)
-#define RBCPR_RESULT0_ERROR_LT0_SHIFT  18
-#define RBCPR_RESULT0_ERROR_SHIFT      6
-#define RBCPR_RESULT0_ERROR_MASK       GENMASK(11, 0)
-#define RBCPR_RESULT0_ERROR_STEPS_SHIFT        2
-#define RBCPR_RESULT0_ERROR_STEPS_MASK GENMASK(3, 0)
-#define RBCPR_RESULT0_STEP_UP_SHIFT    1
-
-/* RBCPR Interrupt Control Register */
-#define REG_RBIF_IRQ_EN(n)             (0x100 + 4 * (n))
-#define REG_RBIF_IRQ_CLEAR             0x110
-#define REG_RBIF_IRQ_STATUS            0x114
-
-#define CPR_INT_DONE           BIT(0)
-#define CPR_INT_MIN            BIT(1)
-#define CPR_INT_DOWN           BIT(2)
-#define CPR_INT_MID            BIT(3)
-#define CPR_INT_UP             BIT(4)
-#define CPR_INT_MAX            BIT(5)
-#define CPR_INT_CLAMP          BIT(6)
-#define CPR_INT_ALL    (CPR_INT_DONE | CPR_INT_MIN | CPR_INT_DOWN | \
-                       CPR_INT_MID | CPR_INT_UP | CPR_INT_MAX | CPR_INT_CLAMP)
-#define CPR_INT_DEFAULT        (CPR_INT_UP | CPR_INT_DOWN)
-
-#define CPR_NUM_RING_OSC       8
-
-/* CPR eFuse parameters */
-#define CPR_FUSE_TARGET_QUOT_BITS_MASK GENMASK(11, 0)
-
-#define CPR_FUSE_MIN_QUOT_DIFF         50
-
-#define FUSE_REVISION_UNKNOWN          (-1)
-
-enum voltage_change_dir {
-       NO_CHANGE,
-       DOWN,
-       UP,
-};
-
-struct cpr_fuse {
-       char *ring_osc;
-       char *init_voltage;
-       char *quotient;
-       char *quotient_offset;
-};
-
-struct fuse_corner_data {
-       int ref_uV;
-       int max_uV;
-       int min_uV;
-       int max_volt_scale;
-       int max_quot_scale;
-       /* fuse quot */
-       int quot_offset;
-       int quot_scale;
-       int quot_adjust;
-       /* fuse quot_offset */
-       int quot_offset_scale;
-       int quot_offset_adjust;
-};
-
-struct cpr_fuses {
-       int init_voltage_step;
-       int init_voltage_width;
-       struct fuse_corner_data *fuse_corner_data;
-};
-
-struct corner_data {
-       unsigned int fuse_corner;
-       unsigned long freq;
-};
-
-struct cpr_desc {
-       unsigned int num_fuse_corners;
-       int min_diff_quot;
-       int *step_quot;
-
-       unsigned int            timer_delay_us;
-       unsigned int            timer_cons_up;
-       unsigned int            timer_cons_down;
-       unsigned int            up_threshold;
-       unsigned int            down_threshold;
-       unsigned int            idle_clocks;
-       unsigned int            gcnt_us;
-       unsigned int            vdd_apc_step_up_limit;
-       unsigned int            vdd_apc_step_down_limit;
-       unsigned int            clamp_timer_interval;
-
-       struct cpr_fuses cpr_fuses;
-       bool reduce_to_fuse_uV;
-       bool reduce_to_corner_uV;
-};
-
-struct acc_desc {
-       unsigned int    enable_reg;
-       u32             enable_mask;
-
-       struct reg_sequence     *config;
-       struct reg_sequence     *settings;
-       int                     num_regs_per_fuse;
-};
-
-struct cpr_acc_desc {
-       const struct cpr_desc *cpr_desc;
-       const struct acc_desc *acc_desc;
-};
-
-struct fuse_corner {
-       int min_uV;
-       int max_uV;
-       int uV;
-       int quot;
-       int step_quot;
-       const struct reg_sequence *accs;
-       int num_accs;
-       unsigned long max_freq;
-       u8 ring_osc_idx;
-};
-
-struct corner {
-       int min_uV;
-       int max_uV;
-       int uV;
-       int last_uV;
-       int quot_adjust;
-       u32 save_ctl;
-       u32 save_irq;
-       unsigned long freq;
-       struct fuse_corner *fuse_corner;
-};
-
-struct cpr_drv {
-       unsigned int            num_corners;
-       unsigned int            ref_clk_khz;
-
-       struct generic_pm_domain pd;
-       struct device           *dev;
-       struct device           *attached_cpu_dev;
-       struct mutex            lock;
-       void __iomem            *base;
-       struct corner           *corner;
-       struct regulator        *vdd_apc;
-       struct clk              *cpu_clk;
-       struct regmap           *tcsr;
-       bool                    loop_disabled;
-       u32                     gcnt;
-       unsigned long           flags;
-
-       struct fuse_corner      *fuse_corners;
-       struct corner           *corners;
-
-       const struct cpr_desc *desc;
-       const struct acc_desc *acc_desc;
-       const struct cpr_fuse *cpr_fuses;
-
-       struct dentry *debugfs;
-};
-
-static bool cpr_is_allowed(struct cpr_drv *drv)
-{
-       return !drv->loop_disabled;
-}
-
-static void cpr_write(struct cpr_drv *drv, u32 offset, u32 value)
-{
-       writel_relaxed(value, drv->base + offset);
-}
-
-static u32 cpr_read(struct cpr_drv *drv, u32 offset)
-{
-       return readl_relaxed(drv->base + offset);
-}
-
-static void
-cpr_masked_write(struct cpr_drv *drv, u32 offset, u32 mask, u32 value)
-{
-       u32 val;
-
-       val = readl_relaxed(drv->base + offset);
-       val &= ~mask;
-       val |= value & mask;
-       writel_relaxed(val, drv->base + offset);
-}
-
-static void cpr_irq_clr(struct cpr_drv *drv)
-{
-       cpr_write(drv, REG_RBIF_IRQ_CLEAR, CPR_INT_ALL);
-}
-
-static void cpr_irq_clr_nack(struct cpr_drv *drv)
-{
-       cpr_irq_clr(drv);
-       cpr_write(drv, REG_RBIF_CONT_NACK_CMD, 1);
-}
-
-static void cpr_irq_clr_ack(struct cpr_drv *drv)
-{
-       cpr_irq_clr(drv);
-       cpr_write(drv, REG_RBIF_CONT_ACK_CMD, 1);
-}
-
-static void cpr_irq_set(struct cpr_drv *drv, u32 int_bits)
-{
-       cpr_write(drv, REG_RBIF_IRQ_EN(0), int_bits);
-}
-
-static void cpr_ctl_modify(struct cpr_drv *drv, u32 mask, u32 value)
-{
-       cpr_masked_write(drv, REG_RBCPR_CTL, mask, value);
-}
-
-static void cpr_ctl_enable(struct cpr_drv *drv, struct corner *corner)
-{
-       u32 val, mask;
-       const struct cpr_desc *desc = drv->desc;
-
-       /* Program Consecutive Up & Down */
-       val = desc->timer_cons_down << RBIF_TIMER_ADJ_CONS_DOWN_SHIFT;
-       val |= desc->timer_cons_up << RBIF_TIMER_ADJ_CONS_UP_SHIFT;
-       mask = RBIF_TIMER_ADJ_CONS_UP_MASK | RBIF_TIMER_ADJ_CONS_DOWN_MASK;
-       cpr_masked_write(drv, REG_RBIF_TIMER_ADJUST, mask, val);
-       cpr_masked_write(drv, REG_RBCPR_CTL,
-                        RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN |
-                        RBCPR_CTL_SW_AUTO_CONT_ACK_EN,
-                        corner->save_ctl);
-       cpr_irq_set(drv, corner->save_irq);
-
-       if (cpr_is_allowed(drv) && corner->max_uV > corner->min_uV)
-               val = RBCPR_CTL_LOOP_EN;
-       else
-               val = 0;
-       cpr_ctl_modify(drv, RBCPR_CTL_LOOP_EN, val);
-}
-
-static void cpr_ctl_disable(struct cpr_drv *drv)
-{
-       cpr_irq_set(drv, 0);
-       cpr_ctl_modify(drv, RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN |
-                      RBCPR_CTL_SW_AUTO_CONT_ACK_EN, 0);
-       cpr_masked_write(drv, REG_RBIF_TIMER_ADJUST,
-                        RBIF_TIMER_ADJ_CONS_UP_MASK |
-                        RBIF_TIMER_ADJ_CONS_DOWN_MASK, 0);
-       cpr_irq_clr(drv);
-       cpr_write(drv, REG_RBIF_CONT_ACK_CMD, 1);
-       cpr_write(drv, REG_RBIF_CONT_NACK_CMD, 1);
-       cpr_ctl_modify(drv, RBCPR_CTL_LOOP_EN, 0);
-}
-
-static bool cpr_ctl_is_enabled(struct cpr_drv *drv)
-{
-       u32 reg_val;
-
-       reg_val = cpr_read(drv, REG_RBCPR_CTL);
-       return reg_val & RBCPR_CTL_LOOP_EN;
-}
-
-static bool cpr_ctl_is_busy(struct cpr_drv *drv)
-{
-       u32 reg_val;
-
-       reg_val = cpr_read(drv, REG_RBCPR_RESULT_0);
-       return reg_val & RBCPR_RESULT0_BUSY_MASK;
-}
-
-static void cpr_corner_save(struct cpr_drv *drv, struct corner *corner)
-{
-       corner->save_ctl = cpr_read(drv, REG_RBCPR_CTL);
-       corner->save_irq = cpr_read(drv, REG_RBIF_IRQ_EN(0));
-}
-
-static void cpr_corner_restore(struct cpr_drv *drv, struct corner *corner)
-{
-       u32 gcnt, ctl, irq, ro_sel, step_quot;
-       struct fuse_corner *fuse = corner->fuse_corner;
-       const struct cpr_desc *desc = drv->desc;
-       int i;
-
-       ro_sel = fuse->ring_osc_idx;
-       gcnt = drv->gcnt;
-       gcnt |= fuse->quot - corner->quot_adjust;
-
-       /* Program the step quotient and idle clocks */
-       step_quot = desc->idle_clocks << RBCPR_STEP_QUOT_IDLE_CLK_SHIFT;
-       step_quot |= fuse->step_quot & RBCPR_STEP_QUOT_STEPQUOT_MASK;
-       cpr_write(drv, REG_RBCPR_STEP_QUOT, step_quot);
-
-       /* Clear the target quotient value and gate count of all ROs */
-       for (i = 0; i < CPR_NUM_RING_OSC; i++)
-               cpr_write(drv, REG_RBCPR_GCNT_TARGET(i), 0);
-
-       cpr_write(drv, REG_RBCPR_GCNT_TARGET(ro_sel), gcnt);
-       ctl = corner->save_ctl;
-       cpr_write(drv, REG_RBCPR_CTL, ctl);
-       irq = corner->save_irq;
-       cpr_irq_set(drv, irq);
-       dev_dbg(drv->dev, "gcnt = %#08x, ctl = %#08x, irq = %#08x\n", gcnt,
-               ctl, irq);
-}
-
-static void cpr_set_acc(struct regmap *tcsr, struct fuse_corner *f,
-                       struct fuse_corner *end)
-{
-       if (f == end)
-               return;
-
-       if (f < end) {
-               for (f += 1; f <= end; f++)
-                       regmap_multi_reg_write(tcsr, f->accs, f->num_accs);
-       } else {
-               for (f -= 1; f >= end; f--)
-                       regmap_multi_reg_write(tcsr, f->accs, f->num_accs);
-       }
-}
-
-static int cpr_pre_voltage(struct cpr_drv *drv,
-                          struct fuse_corner *fuse_corner,
-                          enum voltage_change_dir dir)
-{
-       struct fuse_corner *prev_fuse_corner = drv->corner->fuse_corner;
-
-       if (drv->tcsr && dir == DOWN)
-               cpr_set_acc(drv->tcsr, prev_fuse_corner, fuse_corner);
-
-       return 0;
-}
-
-static int cpr_post_voltage(struct cpr_drv *drv,
-                           struct fuse_corner *fuse_corner,
-                           enum voltage_change_dir dir)
-{
-       struct fuse_corner *prev_fuse_corner = drv->corner->fuse_corner;
-
-       if (drv->tcsr && dir == UP)
-               cpr_set_acc(drv->tcsr, prev_fuse_corner, fuse_corner);
-
-       return 0;
-}
-
-static int cpr_scale_voltage(struct cpr_drv *drv, struct corner *corner,
-                            int new_uV, enum voltage_change_dir dir)
-{
-       int ret;
-       struct fuse_corner *fuse_corner = corner->fuse_corner;
-
-       ret = cpr_pre_voltage(drv, fuse_corner, dir);
-       if (ret)
-               return ret;
-
-       ret = regulator_set_voltage(drv->vdd_apc, new_uV, new_uV);
-       if (ret) {
-               dev_err_ratelimited(drv->dev, "failed to set apc voltage %d\n",
-                                   new_uV);
-               return ret;
-       }
-
-       ret = cpr_post_voltage(drv, fuse_corner, dir);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
-static unsigned int cpr_get_cur_perf_state(struct cpr_drv *drv)
-{
-       return drv->corner ? drv->corner - drv->corners + 1 : 0;
-}
-
-static int cpr_scale(struct cpr_drv *drv, enum voltage_change_dir dir)
-{
-       u32 val, error_steps, reg_mask;
-       int last_uV, new_uV, step_uV, ret;
-       struct corner *corner;
-       const struct cpr_desc *desc = drv->desc;
-
-       if (dir != UP && dir != DOWN)
-               return 0;
-
-       step_uV = regulator_get_linear_step(drv->vdd_apc);
-       if (!step_uV)
-               return -EINVAL;
-
-       corner = drv->corner;
-
-       val = cpr_read(drv, REG_RBCPR_RESULT_0);
-
-       error_steps = val >> RBCPR_RESULT0_ERROR_STEPS_SHIFT;
-       error_steps &= RBCPR_RESULT0_ERROR_STEPS_MASK;
-       last_uV = corner->last_uV;
-
-       if (dir == UP) {
-               if (desc->clamp_timer_interval &&
-                   error_steps < desc->up_threshold) {
-                       /*
-                        * Handle the case where another measurement started
-                        * after the interrupt was triggered due to a core
-                        * exiting from power collapse.
-                        */
-                       error_steps = max(desc->up_threshold,
-                                         desc->vdd_apc_step_up_limit);
-               }
-
-               if (last_uV >= corner->max_uV) {
-                       cpr_irq_clr_nack(drv);
-
-                       /* Maximize the UP threshold */
-                       reg_mask = RBCPR_CTL_UP_THRESHOLD_MASK;
-                       reg_mask <<= RBCPR_CTL_UP_THRESHOLD_SHIFT;
-                       val = reg_mask;
-                       cpr_ctl_modify(drv, reg_mask, val);
-
-                       /* Disable UP interrupt */
-                       cpr_irq_set(drv, CPR_INT_DEFAULT & ~CPR_INT_UP);
-
-                       return 0;
-               }
-
-               if (error_steps > desc->vdd_apc_step_up_limit)
-                       error_steps = desc->vdd_apc_step_up_limit;
-
-               /* Calculate new voltage */
-               new_uV = last_uV + error_steps * step_uV;
-               new_uV = min(new_uV, corner->max_uV);
-
-               dev_dbg(drv->dev,
-                       "UP: -> new_uV: %d last_uV: %d perf state: %u\n",
-                       new_uV, last_uV, cpr_get_cur_perf_state(drv));
-       } else {
-               if (desc->clamp_timer_interval &&
-                   error_steps < desc->down_threshold) {
-                       /*
-                        * Handle the case where another measurement started
-                        * after the interrupt was triggered due to a core
-                        * exiting from power collapse.
-                        */
-                       error_steps = max(desc->down_threshold,
-                                         desc->vdd_apc_step_down_limit);
-               }
-
-               if (last_uV <= corner->min_uV) {
-                       cpr_irq_clr_nack(drv);
-
-                       /* Enable auto nack down */
-                       reg_mask = RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
-                       val = RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
-
-                       cpr_ctl_modify(drv, reg_mask, val);
-
-                       /* Disable DOWN interrupt */
-                       cpr_irq_set(drv, CPR_INT_DEFAULT & ~CPR_INT_DOWN);
-
-                       return 0;
-               }
-
-               if (error_steps > desc->vdd_apc_step_down_limit)
-                       error_steps = desc->vdd_apc_step_down_limit;
-
-               /* Calculate new voltage */
-               new_uV = last_uV - error_steps * step_uV;
-               new_uV = max(new_uV, corner->min_uV);
-
-               dev_dbg(drv->dev,
-                       "DOWN: -> new_uV: %d last_uV: %d perf state: %u\n",
-                       new_uV, last_uV, cpr_get_cur_perf_state(drv));
-       }
-
-       ret = cpr_scale_voltage(drv, corner, new_uV, dir);
-       if (ret) {
-               cpr_irq_clr_nack(drv);
-               return ret;
-       }
-       drv->corner->last_uV = new_uV;
-
-       if (dir == UP) {
-               /* Disable auto nack down */
-               reg_mask = RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
-               val = 0;
-       } else {
-               /* Restore default threshold for UP */
-               reg_mask = RBCPR_CTL_UP_THRESHOLD_MASK;
-               reg_mask <<= RBCPR_CTL_UP_THRESHOLD_SHIFT;
-               val = desc->up_threshold;
-               val <<= RBCPR_CTL_UP_THRESHOLD_SHIFT;
-       }
-
-       cpr_ctl_modify(drv, reg_mask, val);
-
-       /* Re-enable default interrupts */
-       cpr_irq_set(drv, CPR_INT_DEFAULT);
-
-       /* Ack */
-       cpr_irq_clr_ack(drv);
-
-       return 0;
-}
-
-static irqreturn_t cpr_irq_handler(int irq, void *dev)
-{
-       struct cpr_drv *drv = dev;
-       const struct cpr_desc *desc = drv->desc;
-       irqreturn_t ret = IRQ_HANDLED;
-       u32 val;
-
-       mutex_lock(&drv->lock);
-
-       val = cpr_read(drv, REG_RBIF_IRQ_STATUS);
-       if (drv->flags & FLAGS_IGNORE_1ST_IRQ_STATUS)
-               val = cpr_read(drv, REG_RBIF_IRQ_STATUS);
-
-       dev_dbg(drv->dev, "IRQ_STATUS = %#02x\n", val);
-
-       if (!cpr_ctl_is_enabled(drv)) {
-               dev_dbg(drv->dev, "CPR is disabled\n");
-               ret = IRQ_NONE;
-       } else if (cpr_ctl_is_busy(drv) && !desc->clamp_timer_interval) {
-               dev_dbg(drv->dev, "CPR measurement is not ready\n");
-       } else if (!cpr_is_allowed(drv)) {
-               val = cpr_read(drv, REG_RBCPR_CTL);
-               dev_err_ratelimited(drv->dev,
-                                   "Interrupt broken? RBCPR_CTL = %#02x\n",
-                                   val);
-               ret = IRQ_NONE;
-       } else {
-               /*
-                * Following sequence of handling is as per each IRQ's
-                * priority
-                */
-               if (val & CPR_INT_UP) {
-                       cpr_scale(drv, UP);
-               } else if (val & CPR_INT_DOWN) {
-                       cpr_scale(drv, DOWN);
-               } else if (val & CPR_INT_MIN) {
-                       cpr_irq_clr_nack(drv);
-               } else if (val & CPR_INT_MAX) {
-                       cpr_irq_clr_nack(drv);
-               } else if (val & CPR_INT_MID) {
-                       /* RBCPR_CTL_SW_AUTO_CONT_ACK_EN is enabled */
-                       dev_dbg(drv->dev, "IRQ occurred for Mid Flag\n");
-               } else {
-                       dev_dbg(drv->dev,
-                               "IRQ occurred for unknown flag (%#08x)\n", val);
-               }
-
-               /* Save register values for the corner */
-               cpr_corner_save(drv, drv->corner);
-       }
-
-       mutex_unlock(&drv->lock);
-
-       return ret;
-}
-
-static int cpr_enable(struct cpr_drv *drv)
-{
-       int ret;
-
-       ret = regulator_enable(drv->vdd_apc);
-       if (ret)
-               return ret;
-
-       mutex_lock(&drv->lock);
-
-       if (cpr_is_allowed(drv) && drv->corner) {
-               cpr_irq_clr(drv);
-               cpr_corner_restore(drv, drv->corner);
-               cpr_ctl_enable(drv, drv->corner);
-       }
-
-       mutex_unlock(&drv->lock);
-
-       return 0;
-}
-
-static int cpr_disable(struct cpr_drv *drv)
-{
-       mutex_lock(&drv->lock);
-
-       if (cpr_is_allowed(drv)) {
-               cpr_ctl_disable(drv);
-               cpr_irq_clr(drv);
-       }
-
-       mutex_unlock(&drv->lock);
-
-       return regulator_disable(drv->vdd_apc);
-}
-
-static int cpr_config(struct cpr_drv *drv)
-{
-       int i;
-       u32 val, gcnt;
-       struct corner *corner;
-       const struct cpr_desc *desc = drv->desc;
-
-       /* Disable interrupt and CPR */
-       cpr_write(drv, REG_RBIF_IRQ_EN(0), 0);
-       cpr_write(drv, REG_RBCPR_CTL, 0);
-
-       /* Program the default HW ceiling, floor and vlevel */
-       val = (RBIF_LIMIT_CEILING_DEFAULT & RBIF_LIMIT_CEILING_MASK)
-               << RBIF_LIMIT_CEILING_SHIFT;
-       val |= RBIF_LIMIT_FLOOR_DEFAULT & RBIF_LIMIT_FLOOR_MASK;
-       cpr_write(drv, REG_RBIF_LIMIT, val);
-       cpr_write(drv, REG_RBIF_SW_VLEVEL, RBIF_SW_VLEVEL_DEFAULT);
-
-       /*
-        * Clear the target quotient value and gate count of all
-        * ring oscillators
-        */
-       for (i = 0; i < CPR_NUM_RING_OSC; i++)
-               cpr_write(drv, REG_RBCPR_GCNT_TARGET(i), 0);
-
-       /* Init and save gcnt */
-       gcnt = (drv->ref_clk_khz * desc->gcnt_us) / 1000;
-       gcnt = gcnt & RBCPR_GCNT_TARGET_GCNT_MASK;
-       gcnt <<= RBCPR_GCNT_TARGET_GCNT_SHIFT;
-       drv->gcnt = gcnt;
-
-       /* Program the delay count for the timer */
-       val = (drv->ref_clk_khz * desc->timer_delay_us) / 1000;
-       cpr_write(drv, REG_RBCPR_TIMER_INTERVAL, val);
-       dev_dbg(drv->dev, "Timer count: %#0x (for %d us)\n", val,
-               desc->timer_delay_us);
-
-       /* Program Consecutive Up & Down */
-       val = desc->timer_cons_down << RBIF_TIMER_ADJ_CONS_DOWN_SHIFT;
-       val |= desc->timer_cons_up << RBIF_TIMER_ADJ_CONS_UP_SHIFT;
-       val |= desc->clamp_timer_interval << RBIF_TIMER_ADJ_CLAMP_INT_SHIFT;
-       cpr_write(drv, REG_RBIF_TIMER_ADJUST, val);
-
-       /* Program the control register */
-       val = desc->up_threshold << RBCPR_CTL_UP_THRESHOLD_SHIFT;
-       val |= desc->down_threshold << RBCPR_CTL_DN_THRESHOLD_SHIFT;
-       val |= RBCPR_CTL_TIMER_EN | RBCPR_CTL_COUNT_MODE;
-       val |= RBCPR_CTL_SW_AUTO_CONT_ACK_EN;
-       cpr_write(drv, REG_RBCPR_CTL, val);
-
-       for (i = 0; i < drv->num_corners; i++) {
-               corner = &drv->corners[i];
-               corner->save_ctl = val;
-               corner->save_irq = CPR_INT_DEFAULT;
-       }
-
-       cpr_irq_set(drv, CPR_INT_DEFAULT);
-
-       val = cpr_read(drv, REG_RBCPR_VERSION);
-       if (val <= RBCPR_VER_2)
-               drv->flags |= FLAGS_IGNORE_1ST_IRQ_STATUS;
-
-       return 0;
-}
-
-static int cpr_set_performance_state(struct generic_pm_domain *domain,
-                                    unsigned int state)
-{
-       struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd);
-       struct corner *corner, *end;
-       enum voltage_change_dir dir;
-       int ret = 0, new_uV;
-
-       mutex_lock(&drv->lock);
-
-       dev_dbg(drv->dev, "%s: setting perf state: %u (prev state: %u)\n",
-               __func__, state, cpr_get_cur_perf_state(drv));
-
-       /*
-        * Determine new corner we're going to.
-        * Remove one since lowest performance state is 1.
-        */
-       corner = drv->corners + state - 1;
-       end = &drv->corners[drv->num_corners - 1];
-       if (corner > end || corner < drv->corners) {
-               ret = -EINVAL;
-               goto unlock;
-       }
-
-       /* Determine direction */
-       if (drv->corner > corner)
-               dir = DOWN;
-       else if (drv->corner < corner)
-               dir = UP;
-       else
-               dir = NO_CHANGE;
-
-       if (cpr_is_allowed(drv))
-               new_uV = corner->last_uV;
-       else
-               new_uV = corner->uV;
-
-       if (cpr_is_allowed(drv))
-               cpr_ctl_disable(drv);
-
-       ret = cpr_scale_voltage(drv, corner, new_uV, dir);
-       if (ret)
-               goto unlock;
-
-       if (cpr_is_allowed(drv)) {
-               cpr_irq_clr(drv);
-               if (drv->corner != corner)
-                       cpr_corner_restore(drv, corner);
-               cpr_ctl_enable(drv, corner);
-       }
-
-       drv->corner = corner;
-
-unlock:
-       mutex_unlock(&drv->lock);
-
-       return ret;
-}
-
-static int
-cpr_populate_ring_osc_idx(struct cpr_drv *drv)
-{
-       struct fuse_corner *fuse = drv->fuse_corners;
-       struct fuse_corner *end = fuse + drv->desc->num_fuse_corners;
-       const struct cpr_fuse *fuses = drv->cpr_fuses;
-       u32 data;
-       int ret;
-
-       for (; fuse < end; fuse++, fuses++) {
-               ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->ring_osc, &data);
-               if (ret)
-                       return ret;
-               fuse->ring_osc_idx = data;
-       }
-
-       return 0;
-}
-
-static int cpr_read_fuse_uV(const struct cpr_desc *desc,
-                           const struct fuse_corner_data *fdata,
-                           const char *init_v_efuse,
-                           int step_volt,
-                           struct cpr_drv *drv)
-{
-       int step_size_uV, steps, uV;
-       u32 bits = 0;
-       int ret;
-
-       ret = nvmem_cell_read_variable_le_u32(drv->dev, init_v_efuse, &bits);
-       if (ret)
-               return ret;
-
-       steps = bits & ~BIT(desc->cpr_fuses.init_voltage_width - 1);
-       /* Not two's complement.. instead highest bit is sign bit */
-       if (bits & BIT(desc->cpr_fuses.init_voltage_width - 1))
-               steps = -steps;
-
-       step_size_uV = desc->cpr_fuses.init_voltage_step;
-
-       uV = fdata->ref_uV + steps * step_size_uV;
-       return DIV_ROUND_UP(uV, step_volt) * step_volt;
-}
-
-static int cpr_fuse_corner_init(struct cpr_drv *drv)
-{
-       const struct cpr_desc *desc = drv->desc;
-       const struct cpr_fuse *fuses = drv->cpr_fuses;
-       const struct acc_desc *acc_desc = drv->acc_desc;
-       int i;
-       unsigned int step_volt;
-       struct fuse_corner_data *fdata;
-       struct fuse_corner *fuse, *end;
-       int uV;
-       const struct reg_sequence *accs;
-       int ret;
-
-       accs = acc_desc->settings;
-
-       step_volt = regulator_get_linear_step(drv->vdd_apc);
-       if (!step_volt)
-               return -EINVAL;
-
-       /* Populate fuse_corner members */
-       fuse = drv->fuse_corners;
-       end = &fuse[desc->num_fuse_corners - 1];
-       fdata = desc->cpr_fuses.fuse_corner_data;
-
-       for (i = 0; fuse <= end; fuse++, fuses++, i++, fdata++) {
-               /*
-                * Update SoC voltages: platforms might choose a different
-                * regulators than the one used to characterize the algorithms
-                * (ie, init_voltage_step).
-                */
-               fdata->min_uV = roundup(fdata->min_uV, step_volt);
-               fdata->max_uV = roundup(fdata->max_uV, step_volt);
-
-               /* Populate uV */
-               uV = cpr_read_fuse_uV(desc, fdata, fuses->init_voltage,
-                                     step_volt, drv);
-               if (uV < 0)
-                       return uV;
-
-               fuse->min_uV = fdata->min_uV;
-               fuse->max_uV = fdata->max_uV;
-               fuse->uV = clamp(uV, fuse->min_uV, fuse->max_uV);
-
-               if (fuse == end) {
-                       /*
-                        * Allow the highest fuse corner's PVS voltage to
-                        * define the ceiling voltage for that corner in order
-                        * to support SoC's in which variable ceiling values
-                        * are required.
-                        */
-                       end->max_uV = max(end->max_uV, end->uV);
-               }
-
-               /* Populate target quotient by scaling */
-               ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->quotient, &fuse->quot);
-               if (ret)
-                       return ret;
-
-               fuse->quot *= fdata->quot_scale;
-               fuse->quot += fdata->quot_offset;
-               fuse->quot += fdata->quot_adjust;
-               fuse->step_quot = desc->step_quot[fuse->ring_osc_idx];
-
-               /* Populate acc settings */
-               fuse->accs = accs;
-               fuse->num_accs = acc_desc->num_regs_per_fuse;
-               accs += acc_desc->num_regs_per_fuse;
-       }
-
-       /*
-        * Restrict all fuse corner PVS voltages based upon per corner
-        * ceiling and floor voltages.
-        */
-       for (fuse = drv->fuse_corners, i = 0; fuse <= end; fuse++, i++) {
-               if (fuse->uV > fuse->max_uV)
-                       fuse->uV = fuse->max_uV;
-               else if (fuse->uV < fuse->min_uV)
-                       fuse->uV = fuse->min_uV;
-
-               ret = regulator_is_supported_voltage(drv->vdd_apc,
-                                                    fuse->min_uV,
-                                                    fuse->min_uV);
-               if (!ret) {
-                       dev_err(drv->dev,
-                               "min uV: %d (fuse corner: %d) not supported by regulator\n",
-                               fuse->min_uV, i);
-                       return -EINVAL;
-               }
-
-               ret = regulator_is_supported_voltage(drv->vdd_apc,
-                                                    fuse->max_uV,
-                                                    fuse->max_uV);
-               if (!ret) {
-                       dev_err(drv->dev,
-                               "max uV: %d (fuse corner: %d) not supported by regulator\n",
-                               fuse->max_uV, i);
-                       return -EINVAL;
-               }
-
-               dev_dbg(drv->dev,
-                       "fuse corner %d: [%d %d %d] RO%hhu quot %d squot %d\n",
-                       i, fuse->min_uV, fuse->uV, fuse->max_uV,
-                       fuse->ring_osc_idx, fuse->quot, fuse->step_quot);
-       }
-
-       return 0;
-}
-
-static int cpr_calculate_scaling(const char *quot_offset,
-                                struct cpr_drv *drv,
-                                const struct fuse_corner_data *fdata,
-                                const struct corner *corner)
-{
-       u32 quot_diff = 0;
-       unsigned long freq_diff;
-       int scaling;
-       const struct fuse_corner *fuse, *prev_fuse;
-       int ret;
-
-       fuse = corner->fuse_corner;
-       prev_fuse = fuse - 1;
-
-       if (quot_offset) {
-               ret = nvmem_cell_read_variable_le_u32(drv->dev, quot_offset, &quot_diff);
-               if (ret)
-                       return ret;
-
-               quot_diff *= fdata->quot_offset_scale;
-               quot_diff += fdata->quot_offset_adjust;
-       } else {
-               quot_diff = fuse->quot - prev_fuse->quot;
-       }
-
-       freq_diff = fuse->max_freq - prev_fuse->max_freq;
-       freq_diff /= 1000000; /* Convert to MHz */
-       scaling = 1000 * quot_diff / freq_diff;
-       return min(scaling, fdata->max_quot_scale);
-}
-
-static int cpr_interpolate(const struct corner *corner, int step_volt,
-                          const struct fuse_corner_data *fdata)
-{
-       unsigned long f_high, f_low, f_diff;
-       int uV_high, uV_low, uV;
-       u64 temp, temp_limit;
-       const struct fuse_corner *fuse, *prev_fuse;
-
-       fuse = corner->fuse_corner;
-       prev_fuse = fuse - 1;
-
-       f_high = fuse->max_freq;
-       f_low = prev_fuse->max_freq;
-       uV_high = fuse->uV;
-       uV_low = prev_fuse->uV;
-       f_diff = fuse->max_freq - corner->freq;
-
-       /*
-        * Don't interpolate in the wrong direction. This could happen
-        * if the adjusted fuse voltage overlaps with the previous fuse's
-        * adjusted voltage.
-        */
-       if (f_high <= f_low || uV_high <= uV_low || f_high <= corner->freq)
-               return corner->uV;
-
-       temp = f_diff * (uV_high - uV_low);
-       temp = div64_ul(temp, f_high - f_low);
-
-       /*
-        * max_volt_scale has units of uV/MHz while freq values
-        * have units of Hz.  Divide by 1000000 to convert to.
-        */
-       temp_limit = f_diff * fdata->max_volt_scale;
-       do_div(temp_limit, 1000000);
-
-       uV = uV_high - min(temp, temp_limit);
-       return roundup(uV, step_volt);
-}
-
-static unsigned int cpr_get_fuse_corner(struct dev_pm_opp *opp)
-{
-       struct device_node *np;
-       unsigned int fuse_corner = 0;
-
-       np = dev_pm_opp_get_of_node(opp);
-       if (of_property_read_u32(np, "qcom,opp-fuse-level", &fuse_corner))
-               pr_err("%s: missing 'qcom,opp-fuse-level' property\n",
-                      __func__);
-
-       of_node_put(np);
-
-       return fuse_corner;
-}
-
-static unsigned long cpr_get_opp_hz_for_req(struct dev_pm_opp *ref,
-                                           struct device *cpu_dev)
-{
-       u64 rate = 0;
-       struct device_node *ref_np;
-       struct device_node *desc_np;
-       struct device_node *child_np = NULL;
-       struct device_node *child_req_np = NULL;
-
-       desc_np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
-       if (!desc_np)
-               return 0;
-
-       ref_np = dev_pm_opp_get_of_node(ref);
-       if (!ref_np)
-               goto out_ref;
-
-       do {
-               of_node_put(child_req_np);
-               child_np = of_get_next_available_child(desc_np, child_np);
-               child_req_np = of_parse_phandle(child_np, "required-opps", 0);
-       } while (child_np && child_req_np != ref_np);
-
-       if (child_np && child_req_np == ref_np)
-               of_property_read_u64(child_np, "opp-hz", &rate);
-
-       of_node_put(child_req_np);
-       of_node_put(child_np);
-       of_node_put(ref_np);
-out_ref:
-       of_node_put(desc_np);
-
-       return (unsigned long) rate;
-}
-
-static int cpr_corner_init(struct cpr_drv *drv)
-{
-       const struct cpr_desc *desc = drv->desc;
-       const struct cpr_fuse *fuses = drv->cpr_fuses;
-       int i, level, scaling = 0;
-       unsigned int fnum, fc;
-       const char *quot_offset;
-       struct fuse_corner *fuse, *prev_fuse;
-       struct corner *corner, *end;
-       struct corner_data *cdata;
-       const struct fuse_corner_data *fdata;
-       bool apply_scaling;
-       unsigned long freq_diff, freq_diff_mhz;
-       unsigned long freq;
-       int step_volt = regulator_get_linear_step(drv->vdd_apc);
-       struct dev_pm_opp *opp;
-
-       if (!step_volt)
-               return -EINVAL;
-
-       corner = drv->corners;
-       end = &corner[drv->num_corners - 1];
-
-       cdata = devm_kcalloc(drv->dev, drv->num_corners,
-                            sizeof(struct corner_data),
-                            GFP_KERNEL);
-       if (!cdata)
-               return -ENOMEM;
-
-       /*
-        * Store maximum frequency for each fuse corner based on the frequency
-        * plan
-        */
-       for (level = 1; level <= drv->num_corners; level++) {
-               opp = dev_pm_opp_find_level_exact(&drv->pd.dev, level);
-               if (IS_ERR(opp))
-                       return -EINVAL;
-               fc = cpr_get_fuse_corner(opp);
-               if (!fc) {
-                       dev_pm_opp_put(opp);
-                       return -EINVAL;
-               }
-               fnum = fc - 1;
-               freq = cpr_get_opp_hz_for_req(opp, drv->attached_cpu_dev);
-               if (!freq) {
-                       dev_pm_opp_put(opp);
-                       return -EINVAL;
-               }
-               cdata[level - 1].fuse_corner = fnum;
-               cdata[level - 1].freq = freq;
-
-               fuse = &drv->fuse_corners[fnum];
-               dev_dbg(drv->dev, "freq: %lu level: %u fuse level: %u\n",
-                       freq, dev_pm_opp_get_level(opp) - 1, fnum);
-               if (freq > fuse->max_freq)
-                       fuse->max_freq = freq;
-               dev_pm_opp_put(opp);
-       }
-
-       /*
-        * Get the quotient adjustment scaling factor, according to:
-        *
-        * scaling = min(1000 * (QUOT(corner_N) - QUOT(corner_N-1))
-        *              / (freq(corner_N) - freq(corner_N-1)), max_factor)
-        *
-        * QUOT(corner_N):      quotient read from fuse for fuse corner N
-        * QUOT(corner_N-1):    quotient read from fuse for fuse corner (N - 1)
-        * freq(corner_N):      max frequency in MHz supported by fuse corner N
-        * freq(corner_N-1):    max frequency in MHz supported by fuse corner
-        *                       (N - 1)
-        *
-        * Then walk through the corners mapped to each fuse corner
-        * and calculate the quotient adjustment for each one using the
-        * following formula:
-        *
-        * quot_adjust = (freq_max - freq_corner) * scaling / 1000
-        *
-        * freq_max: max frequency in MHz supported by the fuse corner
-        * freq_corner: frequency in MHz corresponding to the corner
-        * scaling: calculated from above equation
-        *
-        *
-        *     +                           +
-        *     |                         v |
-        *   q |           f c           o |           f c
-        *   u |         c               l |         c
-        *   o |       f                 t |       f
-        *   t |     c                   a |     c
-        *     | c f                     g | c f
-        *     |                         e |
-        *     +---------------            +----------------
-        *       0 1 2 3 4 5 6               0 1 2 3 4 5 6
-        *          corner                      corner
-        *
-        *    c = corner
-        *    f = fuse corner
-        *
-        */
-       for (apply_scaling = false, i = 0; corner <= end; corner++, i++) {
-               fnum = cdata[i].fuse_corner;
-               fdata = &desc->cpr_fuses.fuse_corner_data[fnum];
-               quot_offset = fuses[fnum].quotient_offset;
-               fuse = &drv->fuse_corners[fnum];
-               if (fnum)
-                       prev_fuse = &drv->fuse_corners[fnum - 1];
-               else
-                       prev_fuse = NULL;
-
-               corner->fuse_corner = fuse;
-               corner->freq = cdata[i].freq;
-               corner->uV = fuse->uV;
-
-               if (prev_fuse && cdata[i - 1].freq == prev_fuse->max_freq) {
-                       scaling = cpr_calculate_scaling(quot_offset, drv,
-                                                       fdata, corner);
-                       if (scaling < 0)
-                               return scaling;
-
-                       apply_scaling = true;
-               } else if (corner->freq == fuse->max_freq) {
-                       /* This is a fuse corner; don't scale anything */
-                       apply_scaling = false;
-               }
-
-               if (apply_scaling) {
-                       freq_diff = fuse->max_freq - corner->freq;
-                       freq_diff_mhz = freq_diff / 1000000;
-                       corner->quot_adjust = scaling * freq_diff_mhz / 1000;
-
-                       corner->uV = cpr_interpolate(corner, step_volt, fdata);
-               }
-
-               corner->max_uV = fuse->max_uV;
-               corner->min_uV = fuse->min_uV;
-               corner->uV = clamp(corner->uV, corner->min_uV, corner->max_uV);
-               corner->last_uV = corner->uV;
-
-               /* Reduce the ceiling voltage if needed */
-               if (desc->reduce_to_corner_uV && corner->uV < corner->max_uV)
-                       corner->max_uV = corner->uV;
-               else if (desc->reduce_to_fuse_uV && fuse->uV < corner->max_uV)
-                       corner->max_uV = max(corner->min_uV, fuse->uV);
-
-               dev_dbg(drv->dev, "corner %d: [%d %d %d] quot %d\n", i,
-                       corner->min_uV, corner->uV, corner->max_uV,
-                       fuse->quot - corner->quot_adjust);
-       }
-
-       return 0;
-}
-
-static const struct cpr_fuse *cpr_get_fuses(struct cpr_drv *drv)
-{
-       const struct cpr_desc *desc = drv->desc;
-       struct cpr_fuse *fuses;
-       int i;
-
-       fuses = devm_kcalloc(drv->dev, desc->num_fuse_corners,
-                            sizeof(struct cpr_fuse),
-                            GFP_KERNEL);
-       if (!fuses)
-               return ERR_PTR(-ENOMEM);
-
-       for (i = 0; i < desc->num_fuse_corners; i++) {
-               char tbuf[32];
-
-               snprintf(tbuf, 32, "cpr_ring_osc%d", i + 1);
-               fuses[i].ring_osc = devm_kstrdup(drv->dev, tbuf, GFP_KERNEL);
-               if (!fuses[i].ring_osc)
-                       return ERR_PTR(-ENOMEM);
-
-               snprintf(tbuf, 32, "cpr_init_voltage%d", i + 1);
-               fuses[i].init_voltage = devm_kstrdup(drv->dev, tbuf,
-                                                    GFP_KERNEL);
-               if (!fuses[i].init_voltage)
-                       return ERR_PTR(-ENOMEM);
-
-               snprintf(tbuf, 32, "cpr_quotient%d", i + 1);
-               fuses[i].quotient = devm_kstrdup(drv->dev, tbuf, GFP_KERNEL);
-               if (!fuses[i].quotient)
-                       return ERR_PTR(-ENOMEM);
-
-               snprintf(tbuf, 32, "cpr_quotient_offset%d", i + 1);
-               fuses[i].quotient_offset = devm_kstrdup(drv->dev, tbuf,
-                                                       GFP_KERNEL);
-               if (!fuses[i].quotient_offset)
-                       return ERR_PTR(-ENOMEM);
-       }
-
-       return fuses;
-}
-
-static void cpr_set_loop_allowed(struct cpr_drv *drv)
-{
-       drv->loop_disabled = false;
-}
-
-static int cpr_init_parameters(struct cpr_drv *drv)
-{
-       const struct cpr_desc *desc = drv->desc;
-       struct clk *clk;
-
-       clk = clk_get(drv->dev, "ref");
-       if (IS_ERR(clk))
-               return PTR_ERR(clk);
-
-       drv->ref_clk_khz = clk_get_rate(clk) / 1000;
-       clk_put(clk);
-
-       if (desc->timer_cons_up > RBIF_TIMER_ADJ_CONS_UP_MASK ||
-           desc->timer_cons_down > RBIF_TIMER_ADJ_CONS_DOWN_MASK ||
-           desc->up_threshold > RBCPR_CTL_UP_THRESHOLD_MASK ||
-           desc->down_threshold > RBCPR_CTL_DN_THRESHOLD_MASK ||
-           desc->idle_clocks > RBCPR_STEP_QUOT_IDLE_CLK_MASK ||
-           desc->clamp_timer_interval > RBIF_TIMER_ADJ_CLAMP_INT_MASK)
-               return -EINVAL;
-
-       dev_dbg(drv->dev, "up threshold = %u, down threshold = %u\n",
-               desc->up_threshold, desc->down_threshold);
-
-       return 0;
-}
-
-static int cpr_find_initial_corner(struct cpr_drv *drv)
-{
-       unsigned long rate;
-       const struct corner *end;
-       struct corner *iter;
-       unsigned int i = 0;
-
-       if (!drv->cpu_clk) {
-               dev_err(drv->dev, "cannot get rate from NULL clk\n");
-               return -EINVAL;
-       }
-
-       end = &drv->corners[drv->num_corners - 1];
-       rate = clk_get_rate(drv->cpu_clk);
-
-       /*
-        * Some bootloaders set a CPU clock frequency that is not defined
-        * in the OPP table. When running at an unlisted frequency,
-        * cpufreq_online() will change to the OPP which has the lowest
-        * frequency, at or above the unlisted frequency.
-        * Since cpufreq_online() always "rounds up" in the case of an
-        * unlisted frequency, this function always "rounds down" in case
-        * of an unlisted frequency. That way, when cpufreq_online()
-        * triggers the first ever call to cpr_set_performance_state(),
-        * it will correctly determine the direction as UP.
-        */
-       for (iter = drv->corners; iter <= end; iter++) {
-               if (iter->freq > rate)
-                       break;
-               i++;
-               if (iter->freq == rate) {
-                       drv->corner = iter;
-                       break;
-               }
-               if (iter->freq < rate)
-                       drv->corner = iter;
-       }
-
-       if (!drv->corner) {
-               dev_err(drv->dev, "boot up corner not found\n");
-               return -EINVAL;
-       }
-
-       dev_dbg(drv->dev, "boot up perf state: %u\n", i);
-
-       return 0;
-}
-
-static const struct cpr_desc qcs404_cpr_desc = {
-       .num_fuse_corners = 3,
-       .min_diff_quot = CPR_FUSE_MIN_QUOT_DIFF,
-       .step_quot = (int []){ 25, 25, 25, },
-       .timer_delay_us = 5000,
-       .timer_cons_up = 0,
-       .timer_cons_down = 2,
-       .up_threshold = 1,
-       .down_threshold = 3,
-       .idle_clocks = 15,
-       .gcnt_us = 1,
-       .vdd_apc_step_up_limit = 1,
-       .vdd_apc_step_down_limit = 1,
-       .cpr_fuses = {
-               .init_voltage_step = 8000,
-               .init_voltage_width = 6,
-               .fuse_corner_data = (struct fuse_corner_data[]){
-                       /* fuse corner 0 */
-                       {
-                               .ref_uV = 1224000,
-                               .max_uV = 1224000,
-                               .min_uV = 1048000,
-                               .max_volt_scale = 0,
-                               .max_quot_scale = 0,
-                               .quot_offset = 0,
-                               .quot_scale = 1,
-                               .quot_adjust = 0,
-                               .quot_offset_scale = 5,
-                               .quot_offset_adjust = 0,
-                       },
-                       /* fuse corner 1 */
-                       {
-                               .ref_uV = 1288000,
-                               .max_uV = 1288000,
-                               .min_uV = 1048000,
-                               .max_volt_scale = 2000,
-                               .max_quot_scale = 1400,
-                               .quot_offset = 0,
-                               .quot_scale = 1,
-                               .quot_adjust = -20,
-                               .quot_offset_scale = 5,
-                               .quot_offset_adjust = 0,
-                       },
-                       /* fuse corner 2 */
-                       {
-                               .ref_uV = 1352000,
-                               .max_uV = 1384000,
-                               .min_uV = 1088000,
-                               .max_volt_scale = 2000,
-                               .max_quot_scale = 1400,
-                               .quot_offset = 0,
-                               .quot_scale = 1,
-                               .quot_adjust = 0,
-                               .quot_offset_scale = 5,
-                               .quot_offset_adjust = 0,
-                       },
-               },
-       },
-};
-
-static const struct acc_desc qcs404_acc_desc = {
-       .settings = (struct reg_sequence[]){
-               { 0xb120, 0x1041040 },
-               { 0xb124, 0x41 },
-               { 0xb120, 0x0 },
-               { 0xb124, 0x0 },
-               { 0xb120, 0x0 },
-               { 0xb124, 0x0 },
-       },
-       .config = (struct reg_sequence[]){
-               { 0xb138, 0xff },
-               { 0xb130, 0x5555 },
-       },
-       .num_regs_per_fuse = 2,
-};
-
-static const struct cpr_acc_desc qcs404_cpr_acc_desc = {
-       .cpr_desc = &qcs404_cpr_desc,
-       .acc_desc = &qcs404_acc_desc,
-};
-
-static unsigned int cpr_get_performance_state(struct generic_pm_domain *genpd,
-                                             struct dev_pm_opp *opp)
-{
-       return dev_pm_opp_get_level(opp);
-}
-
-static int cpr_power_off(struct generic_pm_domain *domain)
-{
-       struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd);
-
-       return cpr_disable(drv);
-}
-
-static int cpr_power_on(struct generic_pm_domain *domain)
-{
-       struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd);
-
-       return cpr_enable(drv);
-}
-
-static int cpr_pd_attach_dev(struct generic_pm_domain *domain,
-                            struct device *dev)
-{
-       struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd);
-       const struct acc_desc *acc_desc = drv->acc_desc;
-       int ret = 0;
-
-       mutex_lock(&drv->lock);
-
-       dev_dbg(drv->dev, "attach callback for: %s\n", dev_name(dev));
-
-       /*
-        * This driver only supports scaling voltage for a CPU cluster
-        * where all CPUs in the cluster share a single regulator.
-        * Therefore, save the struct device pointer only for the first
-        * CPU device that gets attached. There is no need to do any
-        * additional initialization when further CPUs get attached.
-        */
-       if (drv->attached_cpu_dev)
-               goto unlock;
-
-       /*
-        * cpr_scale_voltage() requires the direction (if we are changing
-        * to a higher or lower OPP). The first time
-        * cpr_set_performance_state() is called, there is no previous
-        * performance state defined. Therefore, we call
-        * cpr_find_initial_corner() that gets the CPU clock frequency
-        * set by the bootloader, so that we can determine the direction
-        * the first time cpr_set_performance_state() is called.
-        */
-       drv->cpu_clk = devm_clk_get(dev, NULL);
-       if (IS_ERR(drv->cpu_clk)) {
-               ret = PTR_ERR(drv->cpu_clk);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(drv->dev, "could not get cpu clk: %d\n", ret);
-               goto unlock;
-       }
-       drv->attached_cpu_dev = dev;
-
-       dev_dbg(drv->dev, "using cpu clk from: %s\n",
-               dev_name(drv->attached_cpu_dev));
-
-       /*
-        * Everything related to (virtual) corners has to be initialized
-        * here, when attaching to the power domain, since we need to know
-        * the maximum frequency for each fuse corner, and this is only
-        * available after the cpufreq driver has attached to us.
-        * The reason for this is that we need to know the highest
-        * frequency associated with each fuse corner.
-        */
-       ret = dev_pm_opp_get_opp_count(&drv->pd.dev);
-       if (ret < 0) {
-               dev_err(drv->dev, "could not get OPP count\n");
-               goto unlock;
-       }
-       drv->num_corners = ret;
-
-       if (drv->num_corners < 2) {
-               dev_err(drv->dev, "need at least 2 OPPs to use CPR\n");
-               ret = -EINVAL;
-               goto unlock;
-       }
-
-       drv->corners = devm_kcalloc(drv->dev, drv->num_corners,
-                                   sizeof(*drv->corners),
-                                   GFP_KERNEL);
-       if (!drv->corners) {
-               ret = -ENOMEM;
-               goto unlock;
-       }
-
-       ret = cpr_corner_init(drv);
-       if (ret)
-               goto unlock;
-
-       cpr_set_loop_allowed(drv);
-
-       ret = cpr_init_parameters(drv);
-       if (ret)
-               goto unlock;
-
-       /* Configure CPR HW but keep it disabled */
-       ret = cpr_config(drv);
-       if (ret)
-               goto unlock;
-
-       ret = cpr_find_initial_corner(drv);
-       if (ret)
-               goto unlock;
-
-       if (acc_desc->config)
-               regmap_multi_reg_write(drv->tcsr, acc_desc->config,
-                                      acc_desc->num_regs_per_fuse);
-
-       /* Enable ACC if required */
-       if (acc_desc->enable_mask)
-               regmap_update_bits(drv->tcsr, acc_desc->enable_reg,
-                                  acc_desc->enable_mask,
-                                  acc_desc->enable_mask);
-
-       dev_info(drv->dev, "driver initialized with %u OPPs\n",
-                drv->num_corners);
-
-unlock:
-       mutex_unlock(&drv->lock);
-
-       return ret;
-}
-
-static int cpr_debug_info_show(struct seq_file *s, void *unused)
-{
-       u32 gcnt, ro_sel, ctl, irq_status, reg, error_steps;
-       u32 step_dn, step_up, error, error_lt0, busy;
-       struct cpr_drv *drv = s->private;
-       struct fuse_corner *fuse_corner;
-       struct corner *corner;
-
-       corner = drv->corner;
-       fuse_corner = corner->fuse_corner;
-
-       seq_printf(s, "corner, current_volt = %d uV\n",
-                      corner->last_uV);
-
-       ro_sel = fuse_corner->ring_osc_idx;
-       gcnt = cpr_read(drv, REG_RBCPR_GCNT_TARGET(ro_sel));
-       seq_printf(s, "rbcpr_gcnt_target (%u) = %#02X\n", ro_sel, gcnt);
-
-       ctl = cpr_read(drv, REG_RBCPR_CTL);
-       seq_printf(s, "rbcpr_ctl = %#02X\n", ctl);
-
-       irq_status = cpr_read(drv, REG_RBIF_IRQ_STATUS);
-       seq_printf(s, "rbcpr_irq_status = %#02X\n", irq_status);
-
-       reg = cpr_read(drv, REG_RBCPR_RESULT_0);
-       seq_printf(s, "rbcpr_result_0 = %#02X\n", reg);
-
-       step_dn = reg & 0x01;
-       step_up = (reg >> RBCPR_RESULT0_STEP_UP_SHIFT) & 0x01;
-       seq_printf(s, "  [step_dn = %u", step_dn);
-
-       seq_printf(s, ", step_up = %u", step_up);
-
-       error_steps = (reg >> RBCPR_RESULT0_ERROR_STEPS_SHIFT)
-                               & RBCPR_RESULT0_ERROR_STEPS_MASK;
-       seq_printf(s, ", error_steps = %u", error_steps);
-
-       error = (reg >> RBCPR_RESULT0_ERROR_SHIFT) & RBCPR_RESULT0_ERROR_MASK;
-       seq_printf(s, ", error = %u", error);
-
-       error_lt0 = (reg >> RBCPR_RESULT0_ERROR_LT0_SHIFT) & 0x01;
-       seq_printf(s, ", error_lt_0 = %u", error_lt0);
-
-       busy = (reg >> RBCPR_RESULT0_BUSY_SHIFT) & 0x01;
-       seq_printf(s, ", busy = %u]\n", busy);
-
-       return 0;
-}
-DEFINE_SHOW_ATTRIBUTE(cpr_debug_info);
-
-static void cpr_debugfs_init(struct cpr_drv *drv)
-{
-       drv->debugfs = debugfs_create_dir("qcom_cpr", NULL);
-
-       debugfs_create_file("debug_info", 0444, drv->debugfs,
-                           drv, &cpr_debug_info_fops);
-}
-
-static int cpr_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct cpr_drv *drv;
-       int irq, ret;
-       const struct cpr_acc_desc *data;
-       struct device_node *np;
-       u32 cpr_rev = FUSE_REVISION_UNKNOWN;
-
-       data = of_device_get_match_data(dev);
-       if (!data || !data->cpr_desc || !data->acc_desc)
-               return -EINVAL;
-
-       drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
-       if (!drv)
-               return -ENOMEM;
-       drv->dev = dev;
-       drv->desc = data->cpr_desc;
-       drv->acc_desc = data->acc_desc;
-
-       drv->fuse_corners = devm_kcalloc(dev, drv->desc->num_fuse_corners,
-                                        sizeof(*drv->fuse_corners),
-                                        GFP_KERNEL);
-       if (!drv->fuse_corners)
-               return -ENOMEM;
-
-       np = of_parse_phandle(dev->of_node, "acc-syscon", 0);
-       if (!np)
-               return -ENODEV;
-
-       drv->tcsr = syscon_node_to_regmap(np);
-       of_node_put(np);
-       if (IS_ERR(drv->tcsr))
-               return PTR_ERR(drv->tcsr);
-
-       drv->base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(drv->base))
-               return PTR_ERR(drv->base);
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return -EINVAL;
-
-       drv->vdd_apc = devm_regulator_get(dev, "vdd-apc");
-       if (IS_ERR(drv->vdd_apc))
-               return PTR_ERR(drv->vdd_apc);
-
-       /*
-        * Initialize fuse corners, since it simply depends
-        * on data in efuses.
-        * Everything related to (virtual) corners has to be
-        * initialized after attaching to the power domain,
-        * since it depends on the CPU's OPP table.
-        */
-       ret = nvmem_cell_read_variable_le_u32(dev, "cpr_fuse_revision", &cpr_rev);
-       if (ret)
-               return ret;
-
-       drv->cpr_fuses = cpr_get_fuses(drv);
-       if (IS_ERR(drv->cpr_fuses))
-               return PTR_ERR(drv->cpr_fuses);
-
-       ret = cpr_populate_ring_osc_idx(drv);
-       if (ret)
-               return ret;
-
-       ret = cpr_fuse_corner_init(drv);
-       if (ret)
-               return ret;
-
-       mutex_init(&drv->lock);
-
-       ret = devm_request_threaded_irq(dev, irq, NULL,
-                                       cpr_irq_handler,
-                                       IRQF_ONESHOT | IRQF_TRIGGER_RISING,
-                                       "cpr", drv);
-       if (ret)
-               return ret;
-
-       drv->pd.name = devm_kstrdup_const(dev, dev->of_node->full_name,
-                                         GFP_KERNEL);
-       if (!drv->pd.name)
-               return -EINVAL;
-
-       drv->pd.power_off = cpr_power_off;
-       drv->pd.power_on = cpr_power_on;
-       drv->pd.set_performance_state = cpr_set_performance_state;
-       drv->pd.opp_to_performance_state = cpr_get_performance_state;
-       drv->pd.attach_dev = cpr_pd_attach_dev;
-
-       ret = pm_genpd_init(&drv->pd, NULL, true);
-       if (ret)
-               return ret;
-
-       ret = of_genpd_add_provider_simple(dev->of_node, &drv->pd);
-       if (ret)
-               goto err_remove_genpd;
-
-       platform_set_drvdata(pdev, drv);
-       cpr_debugfs_init(drv);
-
-       return 0;
-
-err_remove_genpd:
-       pm_genpd_remove(&drv->pd);
-       return ret;
-}
-
-static int cpr_remove(struct platform_device *pdev)
-{
-       struct cpr_drv *drv = platform_get_drvdata(pdev);
-
-       if (cpr_is_allowed(drv)) {
-               cpr_ctl_disable(drv);
-               cpr_irq_set(drv, 0);
-       }
-
-       of_genpd_del_provider(pdev->dev.of_node);
-       pm_genpd_remove(&drv->pd);
-
-       debugfs_remove_recursive(drv->debugfs);
-
-       return 0;
-}
-
-static const struct of_device_id cpr_match_table[] = {
-       { .compatible = "qcom,qcs404-cpr", .data = &qcs404_cpr_acc_desc },
-       { }
-};
-MODULE_DEVICE_TABLE(of, cpr_match_table);
-
-static struct platform_driver cpr_driver = {
-       .probe          = cpr_probe,
-       .remove         = cpr_remove,
-       .driver         = {
-               .name   = "qcom-cpr",
-               .of_match_table = cpr_match_table,
-       },
-};
-module_platform_driver(cpr_driver);
-
-MODULE_DESCRIPTION("Core Power Reduction (CPR) driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/genpd/qcom/rpmhpd.c b/drivers/genpd/qcom/rpmhpd.c
deleted file mode 100644 (file)
index a87e336..0000000
+++ /dev/null
@@ -1,886 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.*/
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/pm_domain.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_opp.h>
-#include <soc/qcom/cmd-db.h>
-#include <soc/qcom/rpmh.h>
-#include <dt-bindings/power/qcom-rpmpd.h>
-#include <dt-bindings/power/qcom,rpmhpd.h>
-
-#define domain_to_rpmhpd(domain) container_of(domain, struct rpmhpd, pd)
-
-#define RPMH_ARC_MAX_LEVELS    16
-
-/**
- * struct rpmhpd - top level RPMh power domain resource data structure
- * @dev:               rpmh power domain controller device
- * @pd:                        generic_pm_domain corresponding to the power domain
- * @parent:            generic_pm_domain corresponding to the parent's power domain
- * @peer:              A peer power domain in case Active only Voting is
- *                     supported
- * @active_only:       True if it represents an Active only peer
- * @corner:            current corner
- * @active_corner:     current active corner
- * @enable_corner:     lowest non-zero corner
- * @level:             An array of level (vlvl) to corner (hlvl) mappings
- *                     derived from cmd-db
- * @level_count:       Number of levels supported by the power domain. max
- *                     being 16 (0 - 15)
- * @enabled:           true if the power domain is enabled
- * @res_name:          Resource name used for cmd-db lookup
- * @addr:              Resource address as looped up using resource name from
- *                     cmd-db
- * @state_synced:      Indicator that sync_state has been invoked for the rpmhpd resource
- */
-struct rpmhpd {
-       struct device   *dev;
-       struct generic_pm_domain pd;
-       struct generic_pm_domain *parent;
-       struct rpmhpd   *peer;
-       const bool      active_only;
-       unsigned int    corner;
-       unsigned int    active_corner;
-       unsigned int    enable_corner;
-       u32             level[RPMH_ARC_MAX_LEVELS];
-       size_t          level_count;
-       bool            enabled;
-       const char      *res_name;
-       u32             addr;
-       bool            state_synced;
-};
-
-struct rpmhpd_desc {
-       struct rpmhpd **rpmhpds;
-       size_t num_pds;
-};
-
-static DEFINE_MUTEX(rpmhpd_lock);
-
-/* RPMH powerdomains */
-
-static struct rpmhpd cx_ao;
-static struct rpmhpd mx;
-static struct rpmhpd mx_ao;
-static struct rpmhpd cx = {
-       .pd = { .name = "cx", },
-       .peer = &cx_ao,
-       .res_name = "cx.lvl",
-};
-
-static struct rpmhpd cx_ao = {
-       .pd = { .name = "cx_ao", },
-       .active_only = true,
-       .peer = &cx,
-       .res_name = "cx.lvl",
-};
-
-static struct rpmhpd cx_ao_w_mx_parent;
-static struct rpmhpd cx_w_mx_parent = {
-       .pd = { .name = "cx", },
-       .peer = &cx_ao_w_mx_parent,
-       .parent = &mx.pd,
-       .res_name = "cx.lvl",
-};
-
-static struct rpmhpd cx_ao_w_mx_parent = {
-       .pd = { .name = "cx_ao", },
-       .active_only = true,
-       .peer = &cx_w_mx_parent,
-       .parent = &mx_ao.pd,
-       .res_name = "cx.lvl",
-};
-
-static struct rpmhpd ebi = {
-       .pd = { .name = "ebi", },
-       .res_name = "ebi.lvl",
-};
-
-static struct rpmhpd gfx = {
-       .pd = { .name = "gfx", },
-       .res_name = "gfx.lvl",
-};
-
-static struct rpmhpd lcx = {
-       .pd = { .name = "lcx", },
-       .res_name = "lcx.lvl",
-};
-
-static struct rpmhpd lmx = {
-       .pd = { .name = "lmx", },
-       .res_name = "lmx.lvl",
-};
-
-static struct rpmhpd mmcx_ao;
-static struct rpmhpd mmcx = {
-       .pd = { .name = "mmcx", },
-       .peer = &mmcx_ao,
-       .res_name = "mmcx.lvl",
-};
-
-static struct rpmhpd mmcx_ao = {
-       .pd = { .name = "mmcx_ao", },
-       .active_only = true,
-       .peer = &mmcx,
-       .res_name = "mmcx.lvl",
-};
-
-static struct rpmhpd mmcx_ao_w_cx_parent;
-static struct rpmhpd mmcx_w_cx_parent = {
-       .pd = { .name = "mmcx", },
-       .peer = &mmcx_ao_w_cx_parent,
-       .parent = &cx.pd,
-       .res_name = "mmcx.lvl",
-};
-
-static struct rpmhpd mmcx_ao_w_cx_parent = {
-       .pd = { .name = "mmcx_ao", },
-       .active_only = true,
-       .peer = &mmcx_w_cx_parent,
-       .parent = &cx_ao.pd,
-       .res_name = "mmcx.lvl",
-};
-
-static struct rpmhpd mss = {
-       .pd = { .name = "mss", },
-       .res_name = "mss.lvl",
-};
-
-static struct rpmhpd mx_ao;
-static struct rpmhpd mx = {
-       .pd = { .name = "mx", },
-       .peer = &mx_ao,
-       .res_name = "mx.lvl",
-};
-
-static struct rpmhpd mx_ao = {
-       .pd = { .name = "mx_ao", },
-       .active_only = true,
-       .peer = &mx,
-       .res_name = "mx.lvl",
-};
-
-static struct rpmhpd mxc_ao;
-static struct rpmhpd mxc = {
-       .pd = { .name = "mxc", },
-       .peer = &mxc_ao,
-       .res_name = "mxc.lvl",
-};
-
-static struct rpmhpd mxc_ao = {
-       .pd = { .name = "mxc_ao", },
-       .active_only = true,
-       .peer = &mxc,
-       .res_name = "mxc.lvl",
-};
-
-static struct rpmhpd nsp = {
-       .pd = { .name = "nsp", },
-       .res_name = "nsp.lvl",
-};
-
-static struct rpmhpd nsp0 = {
-       .pd = { .name = "nsp0", },
-       .res_name = "nsp0.lvl",
-};
-
-static struct rpmhpd nsp1 = {
-       .pd = { .name = "nsp1", },
-       .res_name = "nsp1.lvl",
-};
-
-static struct rpmhpd qphy = {
-       .pd = { .name = "qphy", },
-       .res_name = "qphy.lvl",
-};
-
-/* SA8540P RPMH powerdomains */
-static struct rpmhpd *sa8540p_rpmhpds[] = {
-       [SC8280XP_CX] = &cx,
-       [SC8280XP_CX_AO] = &cx_ao,
-       [SC8280XP_EBI] = &ebi,
-       [SC8280XP_GFX] = &gfx,
-       [SC8280XP_LCX] = &lcx,
-       [SC8280XP_LMX] = &lmx,
-       [SC8280XP_MMCX] = &mmcx,
-       [SC8280XP_MMCX_AO] = &mmcx_ao,
-       [SC8280XP_MX] = &mx,
-       [SC8280XP_MX_AO] = &mx_ao,
-       [SC8280XP_NSP] = &nsp,
-};
-
-static const struct rpmhpd_desc sa8540p_desc = {
-       .rpmhpds = sa8540p_rpmhpds,
-       .num_pds = ARRAY_SIZE(sa8540p_rpmhpds),
-};
-
-/* SA8775P RPMH power domains */
-static struct rpmhpd *sa8775p_rpmhpds[] = {
-       [SA8775P_CX] = &cx,
-       [SA8775P_CX_AO] = &cx_ao,
-       [SA8775P_EBI] = &ebi,
-       [SA8775P_GFX] = &gfx,
-       [SA8775P_LCX] = &lcx,
-       [SA8775P_LMX] = &lmx,
-       [SA8775P_MMCX] = &mmcx,
-       [SA8775P_MMCX_AO] = &mmcx_ao,
-       [SA8775P_MXC] = &mxc,
-       [SA8775P_MXC_AO] = &mxc_ao,
-       [SA8775P_MX] = &mx,
-       [SA8775P_MX_AO] = &mx_ao,
-       [SA8775P_NSP0] = &nsp0,
-       [SA8775P_NSP1] = &nsp1,
-};
-
-static const struct rpmhpd_desc sa8775p_desc = {
-       .rpmhpds = sa8775p_rpmhpds,
-       .num_pds = ARRAY_SIZE(sa8775p_rpmhpds),
-};
-
-/* SDM670 RPMH powerdomains */
-static struct rpmhpd *sdm670_rpmhpds[] = {
-       [SDM670_CX] = &cx_w_mx_parent,
-       [SDM670_CX_AO] = &cx_ao_w_mx_parent,
-       [SDM670_GFX] = &gfx,
-       [SDM670_LCX] = &lcx,
-       [SDM670_LMX] = &lmx,
-       [SDM670_MSS] = &mss,
-       [SDM670_MX] = &mx,
-       [SDM670_MX_AO] = &mx_ao,
-};
-
-static const struct rpmhpd_desc sdm670_desc = {
-       .rpmhpds = sdm670_rpmhpds,
-       .num_pds = ARRAY_SIZE(sdm670_rpmhpds),
-};
-
-/* SDM845 RPMH powerdomains */
-static struct rpmhpd *sdm845_rpmhpds[] = {
-       [SDM845_CX] = &cx_w_mx_parent,
-       [SDM845_CX_AO] = &cx_ao_w_mx_parent,
-       [SDM845_EBI] = &ebi,
-       [SDM845_GFX] = &gfx,
-       [SDM845_LCX] = &lcx,
-       [SDM845_LMX] = &lmx,
-       [SDM845_MSS] = &mss,
-       [SDM845_MX] = &mx,
-       [SDM845_MX_AO] = &mx_ao,
-};
-
-static const struct rpmhpd_desc sdm845_desc = {
-       .rpmhpds = sdm845_rpmhpds,
-       .num_pds = ARRAY_SIZE(sdm845_rpmhpds),
-};
-
-/* SDX55 RPMH powerdomains */
-static struct rpmhpd *sdx55_rpmhpds[] = {
-       [SDX55_CX] = &cx_w_mx_parent,
-       [SDX55_MSS] = &mss,
-       [SDX55_MX] = &mx,
-};
-
-static const struct rpmhpd_desc sdx55_desc = {
-       .rpmhpds = sdx55_rpmhpds,
-       .num_pds = ARRAY_SIZE(sdx55_rpmhpds),
-};
-
-/* SDX65 RPMH powerdomains */
-static struct rpmhpd *sdx65_rpmhpds[] = {
-       [SDX65_CX] = &cx_w_mx_parent,
-       [SDX65_CX_AO] = &cx_ao_w_mx_parent,
-       [SDX65_MSS] = &mss,
-       [SDX65_MX] = &mx,
-       [SDX65_MX_AO] = &mx_ao,
-       [SDX65_MXC] = &mxc,
-};
-
-static const struct rpmhpd_desc sdx65_desc = {
-       .rpmhpds = sdx65_rpmhpds,
-       .num_pds = ARRAY_SIZE(sdx65_rpmhpds),
-};
-
-/* SDX75 RPMH powerdomains */
-static struct rpmhpd *sdx75_rpmhpds[] = {
-       [RPMHPD_CX] = &cx,
-       [RPMHPD_CX_AO] = &cx_ao,
-       [RPMHPD_MSS] = &mss,
-       [RPMHPD_MX] = &mx,
-       [RPMHPD_MX_AO] = &mx_ao,
-       [RPMHPD_MXC] = &mxc,
-};
-
-static const struct rpmhpd_desc sdx75_desc = {
-       .rpmhpds = sdx75_rpmhpds,
-       .num_pds = ARRAY_SIZE(sdx75_rpmhpds),
-};
-
-/* SM6350 RPMH powerdomains */
-static struct rpmhpd *sm6350_rpmhpds[] = {
-       [SM6350_CX] = &cx_w_mx_parent,
-       [SM6350_GFX] = &gfx,
-       [SM6350_LCX] = &lcx,
-       [SM6350_LMX] = &lmx,
-       [SM6350_MSS] = &mss,
-       [SM6350_MX] = &mx,
-};
-
-static const struct rpmhpd_desc sm6350_desc = {
-       .rpmhpds = sm6350_rpmhpds,
-       .num_pds = ARRAY_SIZE(sm6350_rpmhpds),
-};
-
-/* SM8150 RPMH powerdomains */
-static struct rpmhpd *sm8150_rpmhpds[] = {
-       [SM8150_CX] = &cx_w_mx_parent,
-       [SM8150_CX_AO] = &cx_ao_w_mx_parent,
-       [SM8150_EBI] = &ebi,
-       [SM8150_GFX] = &gfx,
-       [SM8150_LCX] = &lcx,
-       [SM8150_LMX] = &lmx,
-       [SM8150_MMCX] = &mmcx,
-       [SM8150_MMCX_AO] = &mmcx_ao,
-       [SM8150_MSS] = &mss,
-       [SM8150_MX] = &mx,
-       [SM8150_MX_AO] = &mx_ao,
-};
-
-static const struct rpmhpd_desc sm8150_desc = {
-       .rpmhpds = sm8150_rpmhpds,
-       .num_pds = ARRAY_SIZE(sm8150_rpmhpds),
-};
-
-static struct rpmhpd *sa8155p_rpmhpds[] = {
-       [SA8155P_CX] = &cx_w_mx_parent,
-       [SA8155P_CX_AO] = &cx_ao_w_mx_parent,
-       [SA8155P_EBI] = &ebi,
-       [SA8155P_GFX] = &gfx,
-       [SA8155P_MSS] = &mss,
-       [SA8155P_MX] = &mx,
-       [SA8155P_MX_AO] = &mx_ao,
-};
-
-static const struct rpmhpd_desc sa8155p_desc = {
-       .rpmhpds = sa8155p_rpmhpds,
-       .num_pds = ARRAY_SIZE(sa8155p_rpmhpds),
-};
-
-/* SM8250 RPMH powerdomains */
-static struct rpmhpd *sm8250_rpmhpds[] = {
-       [RPMHPD_CX] = &cx_w_mx_parent,
-       [RPMHPD_CX_AO] = &cx_ao_w_mx_parent,
-       [RPMHPD_EBI] = &ebi,
-       [RPMHPD_GFX] = &gfx,
-       [RPMHPD_LCX] = &lcx,
-       [RPMHPD_LMX] = &lmx,
-       [RPMHPD_MMCX] = &mmcx,
-       [RPMHPD_MMCX_AO] = &mmcx_ao,
-       [RPMHPD_MX] = &mx,
-       [RPMHPD_MX_AO] = &mx_ao,
-};
-
-static const struct rpmhpd_desc sm8250_desc = {
-       .rpmhpds = sm8250_rpmhpds,
-       .num_pds = ARRAY_SIZE(sm8250_rpmhpds),
-};
-
-/* SM8350 Power domains */
-static struct rpmhpd *sm8350_rpmhpds[] = {
-       [RPMHPD_CX] = &cx_w_mx_parent,
-       [RPMHPD_CX_AO] = &cx_ao_w_mx_parent,
-       [RPMHPD_EBI] = &ebi,
-       [RPMHPD_GFX] = &gfx,
-       [RPMHPD_LCX] = &lcx,
-       [RPMHPD_LMX] = &lmx,
-       [RPMHPD_MMCX] = &mmcx,
-       [RPMHPD_MMCX_AO] = &mmcx_ao,
-       [RPMHPD_MSS] = &mss,
-       [RPMHPD_MX] = &mx,
-       [RPMHPD_MX_AO] = &mx_ao,
-       [RPMHPD_MXC] = &mxc,
-       [RPMHPD_MXC_AO] = &mxc_ao,
-};
-
-static const struct rpmhpd_desc sm8350_desc = {
-       .rpmhpds = sm8350_rpmhpds,
-       .num_pds = ARRAY_SIZE(sm8350_rpmhpds),
-};
-
-/* SM8450 RPMH powerdomains */
-static struct rpmhpd *sm8450_rpmhpds[] = {
-       [RPMHPD_CX] = &cx,
-       [RPMHPD_CX_AO] = &cx_ao,
-       [RPMHPD_EBI] = &ebi,
-       [RPMHPD_GFX] = &gfx,
-       [RPMHPD_LCX] = &lcx,
-       [RPMHPD_LMX] = &lmx,
-       [RPMHPD_MMCX] = &mmcx_w_cx_parent,
-       [RPMHPD_MMCX_AO] = &mmcx_ao_w_cx_parent,
-       [RPMHPD_MSS] = &mss,
-       [RPMHPD_MX] = &mx,
-       [RPMHPD_MX_AO] = &mx_ao,
-       [RPMHPD_MXC] = &mxc,
-       [RPMHPD_MXC_AO] = &mxc_ao,
-};
-
-static const struct rpmhpd_desc sm8450_desc = {
-       .rpmhpds = sm8450_rpmhpds,
-       .num_pds = ARRAY_SIZE(sm8450_rpmhpds),
-};
-
-/* SM8550 RPMH powerdomains */
-static struct rpmhpd *sm8550_rpmhpds[] = {
-       [RPMHPD_CX] = &cx,
-       [RPMHPD_CX_AO] = &cx_ao,
-       [RPMHPD_EBI] = &ebi,
-       [RPMHPD_GFX] = &gfx,
-       [RPMHPD_LCX] = &lcx,
-       [RPMHPD_LMX] = &lmx,
-       [RPMHPD_MMCX] = &mmcx_w_cx_parent,
-       [RPMHPD_MMCX_AO] = &mmcx_ao_w_cx_parent,
-       [RPMHPD_MSS] = &mss,
-       [RPMHPD_MX] = &mx,
-       [RPMHPD_MX_AO] = &mx_ao,
-       [RPMHPD_MXC] = &mxc,
-       [RPMHPD_MXC_AO] = &mxc_ao,
-       [RPMHPD_NSP] = &nsp,
-};
-
-static const struct rpmhpd_desc sm8550_desc = {
-       .rpmhpds = sm8550_rpmhpds,
-       .num_pds = ARRAY_SIZE(sm8550_rpmhpds),
-};
-
-/* QDU1000/QRU1000 RPMH powerdomains */
-static struct rpmhpd *qdu1000_rpmhpds[] = {
-       [QDU1000_CX] = &cx,
-       [QDU1000_EBI] = &ebi,
-       [QDU1000_MSS] = &mss,
-       [QDU1000_MX] = &mx,
-};
-
-static const struct rpmhpd_desc qdu1000_desc = {
-       .rpmhpds = qdu1000_rpmhpds,
-       .num_pds = ARRAY_SIZE(qdu1000_rpmhpds),
-};
-
-/* SC7180 RPMH powerdomains */
-static struct rpmhpd *sc7180_rpmhpds[] = {
-       [SC7180_CX] = &cx_w_mx_parent,
-       [SC7180_CX_AO] = &cx_ao_w_mx_parent,
-       [SC7180_GFX] = &gfx,
-       [SC7180_LCX] = &lcx,
-       [SC7180_LMX] = &lmx,
-       [SC7180_MSS] = &mss,
-       [SC7180_MX] = &mx,
-       [SC7180_MX_AO] = &mx_ao,
-};
-
-static const struct rpmhpd_desc sc7180_desc = {
-       .rpmhpds = sc7180_rpmhpds,
-       .num_pds = ARRAY_SIZE(sc7180_rpmhpds),
-};
-
-/* SC7280 RPMH powerdomains */
-static struct rpmhpd *sc7280_rpmhpds[] = {
-       [SC7280_CX] = &cx,
-       [SC7280_CX_AO] = &cx_ao,
-       [SC7280_EBI] = &ebi,
-       [SC7280_GFX] = &gfx,
-       [SC7280_LCX] = &lcx,
-       [SC7280_LMX] = &lmx,
-       [SC7280_MSS] = &mss,
-       [SC7280_MX] = &mx,
-       [SC7280_MX_AO] = &mx_ao,
-};
-
-static const struct rpmhpd_desc sc7280_desc = {
-       .rpmhpds = sc7280_rpmhpds,
-       .num_pds = ARRAY_SIZE(sc7280_rpmhpds),
-};
-
-/* SC8180x RPMH powerdomains */
-static struct rpmhpd *sc8180x_rpmhpds[] = {
-       [SC8180X_CX] = &cx_w_mx_parent,
-       [SC8180X_CX_AO] = &cx_ao_w_mx_parent,
-       [SC8180X_EBI] = &ebi,
-       [SC8180X_GFX] = &gfx,
-       [SC8180X_LCX] = &lcx,
-       [SC8180X_LMX] = &lmx,
-       [SC8180X_MMCX] = &mmcx,
-       [SC8180X_MMCX_AO] = &mmcx_ao,
-       [SC8180X_MSS] = &mss,
-       [SC8180X_MX] = &mx,
-       [SC8180X_MX_AO] = &mx_ao,
-};
-
-static const struct rpmhpd_desc sc8180x_desc = {
-       .rpmhpds = sc8180x_rpmhpds,
-       .num_pds = ARRAY_SIZE(sc8180x_rpmhpds),
-};
-
-/* SC8280xp RPMH powerdomains */
-static struct rpmhpd *sc8280xp_rpmhpds[] = {
-       [SC8280XP_CX] = &cx,
-       [SC8280XP_CX_AO] = &cx_ao,
-       [SC8280XP_EBI] = &ebi,
-       [SC8280XP_GFX] = &gfx,
-       [SC8280XP_LCX] = &lcx,
-       [SC8280XP_LMX] = &lmx,
-       [SC8280XP_MMCX] = &mmcx,
-       [SC8280XP_MMCX_AO] = &mmcx_ao,
-       [SC8280XP_MX] = &mx,
-       [SC8280XP_MX_AO] = &mx_ao,
-       [SC8280XP_NSP] = &nsp,
-       [SC8280XP_QPHY] = &qphy,
-};
-
-static const struct rpmhpd_desc sc8280xp_desc = {
-       .rpmhpds = sc8280xp_rpmhpds,
-       .num_pds = ARRAY_SIZE(sc8280xp_rpmhpds),
-};
-
-static const struct of_device_id rpmhpd_match_table[] = {
-       { .compatible = "qcom,qdu1000-rpmhpd", .data = &qdu1000_desc },
-       { .compatible = "qcom,sa8155p-rpmhpd", .data = &sa8155p_desc },
-       { .compatible = "qcom,sa8540p-rpmhpd", .data = &sa8540p_desc },
-       { .compatible = "qcom,sa8775p-rpmhpd", .data = &sa8775p_desc },
-       { .compatible = "qcom,sc7180-rpmhpd", .data = &sc7180_desc },
-       { .compatible = "qcom,sc7280-rpmhpd", .data = &sc7280_desc },
-       { .compatible = "qcom,sc8180x-rpmhpd", .data = &sc8180x_desc },
-       { .compatible = "qcom,sc8280xp-rpmhpd", .data = &sc8280xp_desc },
-       { .compatible = "qcom,sdm670-rpmhpd", .data = &sdm670_desc },
-       { .compatible = "qcom,sdm845-rpmhpd", .data = &sdm845_desc },
-       { .compatible = "qcom,sdx55-rpmhpd", .data = &sdx55_desc},
-       { .compatible = "qcom,sdx65-rpmhpd", .data = &sdx65_desc},
-       { .compatible = "qcom,sdx75-rpmhpd", .data = &sdx75_desc},
-       { .compatible = "qcom,sm6350-rpmhpd", .data = &sm6350_desc },
-       { .compatible = "qcom,sm8150-rpmhpd", .data = &sm8150_desc },
-       { .compatible = "qcom,sm8250-rpmhpd", .data = &sm8250_desc },
-       { .compatible = "qcom,sm8350-rpmhpd", .data = &sm8350_desc },
-       { .compatible = "qcom,sm8450-rpmhpd", .data = &sm8450_desc },
-       { .compatible = "qcom,sm8550-rpmhpd", .data = &sm8550_desc },
-       { }
-};
-MODULE_DEVICE_TABLE(of, rpmhpd_match_table);
-
-static int rpmhpd_send_corner(struct rpmhpd *pd, int state,
-                             unsigned int corner, bool sync)
-{
-       struct tcs_cmd cmd = {
-               .addr = pd->addr,
-               .data = corner,
-       };
-
-       /*
-        * Wait for an ack only when we are increasing the
-        * perf state of the power domain
-        */
-       if (sync)
-               return rpmh_write(pd->dev, state, &cmd, 1);
-       else
-               return rpmh_write_async(pd->dev, state, &cmd, 1);
-}
-
-static void to_active_sleep(struct rpmhpd *pd, unsigned int corner,
-                           unsigned int *active, unsigned int *sleep)
-{
-       *active = corner;
-
-       if (pd->active_only)
-               *sleep = 0;
-       else
-               *sleep = *active;
-}
-
-/*
- * This function is used to aggregate the votes across the active only
- * resources and its peers. The aggregated votes are sent to RPMh as
- * ACTIVE_ONLY votes (which take effect immediately), as WAKE_ONLY votes
- * (applied by RPMh on system wakeup) and as SLEEP votes (applied by RPMh
- * on system sleep).
- * We send ACTIVE_ONLY votes for resources without any peers. For others,
- * which have an active only peer, all 3 votes are sent.
- */
-static int rpmhpd_aggregate_corner(struct rpmhpd *pd, unsigned int corner)
-{
-       int ret;
-       struct rpmhpd *peer = pd->peer;
-       unsigned int active_corner, sleep_corner;
-       unsigned int this_active_corner = 0, this_sleep_corner = 0;
-       unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
-
-       if (pd->state_synced) {
-               to_active_sleep(pd, corner, &this_active_corner, &this_sleep_corner);
-       } else {
-               /* Clamp to highest corner if sync_state hasn't happened */
-               this_active_corner = pd->level_count - 1;
-               this_sleep_corner = pd->level_count - 1;
-       }
-
-       if (peer && peer->enabled)
-               to_active_sleep(peer, peer->corner, &peer_active_corner,
-                               &peer_sleep_corner);
-
-       active_corner = max(this_active_corner, peer_active_corner);
-
-       ret = rpmhpd_send_corner(pd, RPMH_ACTIVE_ONLY_STATE, active_corner,
-                                active_corner > pd->active_corner);
-       if (ret)
-               return ret;
-
-       pd->active_corner = active_corner;
-
-       if (peer) {
-               peer->active_corner = active_corner;
-
-               ret = rpmhpd_send_corner(pd, RPMH_WAKE_ONLY_STATE,
-                                        active_corner, false);
-               if (ret)
-                       return ret;
-
-               sleep_corner = max(this_sleep_corner, peer_sleep_corner);
-
-               return rpmhpd_send_corner(pd, RPMH_SLEEP_STATE, sleep_corner,
-                                         false);
-       }
-
-       return ret;
-}
-
-static int rpmhpd_power_on(struct generic_pm_domain *domain)
-{
-       struct rpmhpd *pd = domain_to_rpmhpd(domain);
-       unsigned int corner;
-       int ret;
-
-       mutex_lock(&rpmhpd_lock);
-
-       corner = max(pd->corner, pd->enable_corner);
-       ret = rpmhpd_aggregate_corner(pd, corner);
-       if (!ret)
-               pd->enabled = true;
-
-       mutex_unlock(&rpmhpd_lock);
-
-       return ret;
-}
-
-static int rpmhpd_power_off(struct generic_pm_domain *domain)
-{
-       struct rpmhpd *pd = domain_to_rpmhpd(domain);
-       int ret;
-
-       mutex_lock(&rpmhpd_lock);
-
-       ret = rpmhpd_aggregate_corner(pd, 0);
-       if (!ret)
-               pd->enabled = false;
-
-       mutex_unlock(&rpmhpd_lock);
-
-       return ret;
-}
-
-static int rpmhpd_set_performance_state(struct generic_pm_domain *domain,
-                                       unsigned int level)
-{
-       struct rpmhpd *pd = domain_to_rpmhpd(domain);
-       int ret = 0, i;
-
-       mutex_lock(&rpmhpd_lock);
-
-       for (i = 0; i < pd->level_count; i++)
-               if (level <= pd->level[i])
-                       break;
-
-       /*
-        * If the level requested is more than that supported by the
-        * max corner, just set it to max anyway.
-        */
-       if (i == pd->level_count)
-               i--;
-
-       if (pd->enabled) {
-               /* Ensure that the domain isn't turn off */
-               if (i < pd->enable_corner)
-                       i = pd->enable_corner;
-
-               ret = rpmhpd_aggregate_corner(pd, i);
-               if (ret)
-                       goto out;
-       }
-
-       pd->corner = i;
-out:
-       mutex_unlock(&rpmhpd_lock);
-
-       return ret;
-}
-
-static unsigned int rpmhpd_get_performance_state(struct generic_pm_domain *genpd,
-                                                struct dev_pm_opp *opp)
-{
-       return dev_pm_opp_get_level(opp);
-}
-
-static int rpmhpd_update_level_mapping(struct rpmhpd *rpmhpd)
-{
-       int i;
-       const u16 *buf;
-
-       buf = cmd_db_read_aux_data(rpmhpd->res_name, &rpmhpd->level_count);
-       if (IS_ERR(buf))
-               return PTR_ERR(buf);
-
-       /* 2 bytes used for each command DB aux data entry */
-       rpmhpd->level_count >>= 1;
-
-       if (rpmhpd->level_count > RPMH_ARC_MAX_LEVELS)
-               return -EINVAL;
-
-       for (i = 0; i < rpmhpd->level_count; i++) {
-               rpmhpd->level[i] = buf[i];
-
-               /* Remember the first corner with non-zero level */
-               if (!rpmhpd->level[rpmhpd->enable_corner] && rpmhpd->level[i])
-                       rpmhpd->enable_corner = i;
-
-               /*
-                * The AUX data may be zero padded.  These 0 valued entries at
-                * the end of the map must be ignored.
-                */
-               if (i > 0 && rpmhpd->level[i] == 0) {
-                       rpmhpd->level_count = i;
-                       break;
-               }
-               pr_debug("%s: ARC hlvl=%2d --> vlvl=%4u\n", rpmhpd->res_name, i,
-                        rpmhpd->level[i]);
-       }
-
-       return 0;
-}
-
-static int rpmhpd_probe(struct platform_device *pdev)
-{
-       int i, ret;
-       size_t num_pds;
-       struct device *dev = &pdev->dev;
-       struct genpd_onecell_data *data;
-       struct rpmhpd **rpmhpds;
-       const struct rpmhpd_desc *desc;
-
-       desc = of_device_get_match_data(dev);
-       if (!desc)
-               return -EINVAL;
-
-       rpmhpds = desc->rpmhpds;
-       num_pds = desc->num_pds;
-
-       data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       data->domains = devm_kcalloc(dev, num_pds, sizeof(*data->domains),
-                                    GFP_KERNEL);
-       if (!data->domains)
-               return -ENOMEM;
-
-       data->num_domains = num_pds;
-
-       for (i = 0; i < num_pds; i++) {
-               if (!rpmhpds[i])
-                       continue;
-
-               rpmhpds[i]->dev = dev;
-               rpmhpds[i]->addr = cmd_db_read_addr(rpmhpds[i]->res_name);
-               if (!rpmhpds[i]->addr) {
-                       dev_err(dev, "Could not find RPMh address for resource %s\n",
-                               rpmhpds[i]->res_name);
-                       return -ENODEV;
-               }
-
-               ret = cmd_db_read_slave_id(rpmhpds[i]->res_name);
-               if (ret != CMD_DB_HW_ARC) {
-                       dev_err(dev, "RPMh slave ID mismatch\n");
-                       return -EINVAL;
-               }
-
-               ret = rpmhpd_update_level_mapping(rpmhpds[i]);
-               if (ret)
-                       return ret;
-
-               rpmhpds[i]->pd.power_off = rpmhpd_power_off;
-               rpmhpds[i]->pd.power_on = rpmhpd_power_on;
-               rpmhpds[i]->pd.set_performance_state = rpmhpd_set_performance_state;
-               rpmhpds[i]->pd.opp_to_performance_state = rpmhpd_get_performance_state;
-               pm_genpd_init(&rpmhpds[i]->pd, NULL, true);
-
-               data->domains[i] = &rpmhpds[i]->pd;
-       }
-
-       /* Add subdomains */
-       for (i = 0; i < num_pds; i++) {
-               if (!rpmhpds[i])
-                       continue;
-               if (rpmhpds[i]->parent)
-                       pm_genpd_add_subdomain(rpmhpds[i]->parent,
-                                              &rpmhpds[i]->pd);
-       }
-
-       return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
-}
-
-static void rpmhpd_sync_state(struct device *dev)
-{
-       const struct rpmhpd_desc *desc = of_device_get_match_data(dev);
-       struct rpmhpd **rpmhpds = desc->rpmhpds;
-       unsigned int corner;
-       struct rpmhpd *pd;
-       unsigned int i;
-       int ret;
-
-       mutex_lock(&rpmhpd_lock);
-       for (i = 0; i < desc->num_pds; i++) {
-               pd = rpmhpds[i];
-               if (!pd)
-                       continue;
-
-               pd->state_synced = true;
-               if (pd->enabled)
-                       corner = max(pd->corner, pd->enable_corner);
-               else
-                       corner = 0;
-
-               ret = rpmhpd_aggregate_corner(pd, corner);
-               if (ret)
-                       dev_err(dev, "failed to sync %s\n", pd->res_name);
-       }
-       mutex_unlock(&rpmhpd_lock);
-}
-
-static struct platform_driver rpmhpd_driver = {
-       .driver = {
-               .name = "qcom-rpmhpd",
-               .of_match_table = rpmhpd_match_table,
-               .suppress_bind_attrs = true,
-               .sync_state = rpmhpd_sync_state,
-       },
-       .probe = rpmhpd_probe,
-};
-
-static int __init rpmhpd_init(void)
-{
-       return platform_driver_register(&rpmhpd_driver);
-}
-core_initcall(rpmhpd_init);
-
-MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPMh Power Domain Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/genpd/qcom/rpmpd.c b/drivers/genpd/qcom/rpmpd.c
deleted file mode 100644 (file)
index 3135dd1..0000000
+++ /dev/null
@@ -1,1023 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. */
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/pm_domain.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_opp.h>
-#include <linux/soc/qcom/smd-rpm.h>
-
-#include <dt-bindings/power/qcom-rpmpd.h>
-
-#define domain_to_rpmpd(domain) container_of(domain, struct rpmpd, pd)
-
-/* Resource types:
- * RPMPD_X is X encoded as a little-endian, lower-case, ASCII string */
-#define RPMPD_SMPA 0x61706d73
-#define RPMPD_LDOA 0x616f646c
-#define RPMPD_SMPB 0x62706d73
-#define RPMPD_LDOB 0x626f646c
-#define RPMPD_RWCX 0x78637772
-#define RPMPD_RWMX 0x786d7772
-#define RPMPD_RWLC 0x636c7772
-#define RPMPD_RWLM 0x6d6c7772
-#define RPMPD_RWSC 0x63737772
-#define RPMPD_RWSM 0x6d737772
-#define RPMPD_RWGX 0x78677772
-
-/* Operation Keys */
-#define KEY_CORNER             0x6e726f63 /* corn */
-#define KEY_ENABLE             0x6e657773 /* swen */
-#define KEY_FLOOR_CORNER       0x636676   /* vfc */
-#define KEY_FLOOR_LEVEL                0x6c6676   /* vfl */
-#define KEY_LEVEL              0x6c766c76 /* vlvl */
-
-#define MAX_CORNER_RPMPD_STATE 6
-
-struct rpmpd_req {
-       __le32 key;
-       __le32 nbytes;
-       __le32 value;
-};
-
-struct rpmpd {
-       struct generic_pm_domain pd;
-       struct generic_pm_domain *parent;
-       struct rpmpd *peer;
-       const bool active_only;
-       unsigned int corner;
-       bool enabled;
-       const int res_type;
-       const int res_id;
-       struct qcom_smd_rpm *rpm;
-       unsigned int max_state;
-       __le32 key;
-       bool state_synced;
-};
-
-struct rpmpd_desc {
-       struct rpmpd **rpmpds;
-       size_t num_pds;
-       unsigned int max_state;
-};
-
-static DEFINE_MUTEX(rpmpd_lock);
-
-/* CX */
-static struct rpmpd cx_rwcx0_lvl_ao;
-static struct rpmpd cx_rwcx0_lvl = {
-       .pd = { .name = "cx", },
-       .peer = &cx_rwcx0_lvl_ao,
-       .res_type = RPMPD_RWCX,
-       .res_id = 0,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd cx_rwcx0_lvl_ao = {
-       .pd = { .name = "cx_ao", },
-       .peer = &cx_rwcx0_lvl,
-       .active_only = true,
-       .res_type = RPMPD_RWCX,
-       .res_id = 0,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd cx_s1a_corner_ao;
-static struct rpmpd cx_s1a_corner = {
-       .pd = { .name = "cx", },
-       .peer = &cx_s1a_corner_ao,
-       .res_type = RPMPD_SMPA,
-       .res_id = 1,
-       .key = KEY_CORNER,
-};
-
-static struct rpmpd cx_s1a_corner_ao = {
-       .pd = { .name = "cx_ao", },
-       .peer = &cx_s1a_corner,
-       .active_only = true,
-       .res_type = RPMPD_SMPA,
-       .res_id = 1,
-       .key = KEY_CORNER,
-};
-
-static struct rpmpd cx_s2a_corner_ao;
-static struct rpmpd cx_s2a_corner = {
-       .pd = { .name = "cx", },
-       .peer = &cx_s2a_corner_ao,
-       .res_type = RPMPD_SMPA,
-       .res_id = 2,
-       .key = KEY_CORNER,
-};
-
-static struct rpmpd cx_s2a_corner_ao = {
-       .pd = { .name = "cx_ao", },
-       .peer = &cx_s2a_corner,
-       .active_only = true,
-       .res_type = RPMPD_SMPA,
-       .res_id = 2,
-       .key = KEY_CORNER,
-};
-
-static struct rpmpd cx_s2a_lvl_ao;
-static struct rpmpd cx_s2a_lvl = {
-       .pd = { .name = "cx", },
-       .peer = &cx_s2a_lvl_ao,
-       .res_type = RPMPD_SMPA,
-       .res_id = 2,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd cx_s2a_lvl_ao = {
-       .pd = { .name = "cx_ao", },
-       .peer = &cx_s2a_lvl,
-       .active_only = true,
-       .res_type = RPMPD_SMPA,
-       .res_id = 2,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd cx_s3a_lvl_ao;
-static struct rpmpd cx_s3a_lvl = {
-       .pd = { .name = "cx", },
-       .peer = &cx_s3a_lvl_ao,
-       .res_type = RPMPD_SMPA,
-       .res_id = 3,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd cx_s3a_lvl_ao = {
-       .pd = { .name = "cx_ao", },
-       .peer = &cx_s3a_lvl,
-       .active_only = true,
-       .res_type = RPMPD_SMPA,
-       .res_id = 3,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd cx_rwcx0_vfl = {
-       .pd = { .name = "cx_vfl", },
-       .res_type = RPMPD_RWCX,
-       .res_id = 0,
-       .key = KEY_FLOOR_LEVEL,
-};
-
-static struct rpmpd cx_rwsc2_vfl = {
-       .pd = { .name = "cx_vfl", },
-       .res_type = RPMPD_RWSC,
-       .res_id = 2,
-       .key = KEY_FLOOR_LEVEL,
-};
-
-static struct rpmpd cx_s1a_vfc = {
-       .pd = { .name = "cx_vfc", },
-       .res_type = RPMPD_SMPA,
-       .res_id = 1,
-       .key = KEY_FLOOR_CORNER,
-};
-
-static struct rpmpd cx_s2a_vfc = {
-       .pd = { .name = "cx_vfc", },
-       .res_type = RPMPD_SMPA,
-       .res_id = 2,
-       .key = KEY_FLOOR_CORNER,
-};
-
-static struct rpmpd cx_s2a_vfl = {
-       .pd = { .name = "cx_vfl", },
-       .res_type = RPMPD_SMPA,
-       .res_id = 2,
-       .key = KEY_FLOOR_LEVEL,
-};
-
-static struct rpmpd cx_s3a_vfl = {
-       .pd = { .name = "cx_vfl", },
-       .res_type = RPMPD_SMPA,
-       .res_id = 3,
-       .key = KEY_FLOOR_LEVEL,
-};
-
-/* G(F)X */
-static struct rpmpd gfx_s2b_corner = {
-       .pd = { .name = "gfx", },
-       .res_type = RPMPD_SMPB,
-       .res_id = 2,
-       .key = KEY_CORNER,
-};
-
-static struct rpmpd gfx_s2b_vfc = {
-       .pd = { .name = "gfx_vfc", },
-       .res_type = RPMPD_SMPB,
-       .res_id = 2,
-       .key = KEY_FLOOR_CORNER,
-};
-
-static struct rpmpd mx_rwmx0_lvl;
-static struct rpmpd gx_rwgx0_lvl_ao;
-static struct rpmpd gx_rwgx0_lvl = {
-       .pd = { .name = "gx", },
-       .peer = &gx_rwgx0_lvl_ao,
-       .res_type = RPMPD_RWGX,
-       .parent = &mx_rwmx0_lvl.pd,
-       .res_id = 0,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd mx_rwmx0_lvl_ao;
-static struct rpmpd gx_rwgx0_lvl_ao = {
-       .pd = { .name = "gx_ao", },
-       .peer = &gx_rwgx0_lvl,
-       .parent = &mx_rwmx0_lvl_ao.pd,
-       .active_only = true,
-       .res_type = RPMPD_RWGX,
-       .res_id = 0,
-       .key = KEY_LEVEL,
-};
-
-/* MX */
-static struct rpmpd mx_l3a_corner_ao;
-static struct rpmpd mx_l3a_corner = {
-       .pd = { .name = "mx", },
-       .peer = &mx_l3a_corner_ao,
-       .res_type = RPMPD_LDOA,
-       .res_id = 3,
-       .key = KEY_CORNER,
-};
-
-static struct rpmpd mx_l3a_corner_ao = {
-       .pd = { .name = "mx_ao", },
-       .peer = &mx_l3a_corner,
-       .active_only = true,
-       .res_type = RPMPD_LDOA,
-       .res_id = 3,
-       .key = KEY_CORNER,
-};
-
-static struct rpmpd mx_l12a_lvl_ao;
-static struct rpmpd mx_l12a_lvl = {
-       .pd = { .name = "mx", },
-       .peer = &mx_l12a_lvl_ao,
-       .res_type = RPMPD_LDOA,
-       .res_id = 12,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd mx_l12a_lvl_ao = {
-       .pd = { .name = "mx_ao", },
-       .peer = &mx_l12a_lvl,
-       .active_only = true,
-       .res_type = RPMPD_LDOA,
-       .res_id = 12,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd mx_s2a_corner_ao;
-static struct rpmpd mx_s2a_corner = {
-       .pd = { .name = "mx", },
-       .peer = &mx_s2a_corner_ao,
-       .res_type = RPMPD_SMPA,
-       .res_id = 2,
-       .key = KEY_CORNER,
-};
-
-static struct rpmpd mx_s2a_corner_ao = {
-       .pd = { .name = "mx_ao", },
-       .peer = &mx_s2a_corner,
-       .active_only = true,
-       .res_type = RPMPD_SMPA,
-       .res_id = 2,
-       .key = KEY_CORNER,
-};
-
-static struct rpmpd mx_rwmx0_lvl_ao;
-static struct rpmpd mx_rwmx0_lvl = {
-       .pd = { .name = "mx", },
-       .peer = &mx_rwmx0_lvl_ao,
-       .res_type = RPMPD_RWMX,
-       .res_id = 0,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd mx_rwmx0_lvl_ao = {
-       .pd = { .name = "mx_ao", },
-       .peer = &mx_rwmx0_lvl,
-       .active_only = true,
-       .res_type = RPMPD_RWMX,
-       .res_id = 0,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd mx_s6a_lvl_ao;
-static struct rpmpd mx_s6a_lvl = {
-       .pd = { .name = "mx", },
-       .peer = &mx_s6a_lvl_ao,
-       .res_type = RPMPD_SMPA,
-       .res_id = 6,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd mx_s6a_lvl_ao = {
-       .pd = { .name = "mx_ao", },
-       .peer = &mx_s6a_lvl,
-       .active_only = true,
-       .res_type = RPMPD_SMPA,
-       .res_id = 6,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd mx_s7a_lvl_ao;
-static struct rpmpd mx_s7a_lvl = {
-       .pd = { .name = "mx", },
-       .peer = &mx_s7a_lvl_ao,
-       .res_type = RPMPD_SMPA,
-       .res_id = 7,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd mx_s7a_lvl_ao = {
-       .pd = { .name = "mx_ao", },
-       .peer = &mx_s7a_lvl,
-       .active_only = true,
-       .res_type = RPMPD_SMPA,
-       .res_id = 7,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd mx_l12a_vfl = {
-       .pd = { .name = "mx_vfl", },
-       .res_type = RPMPD_LDOA,
-       .res_id = 12,
-       .key = KEY_FLOOR_LEVEL,
-};
-
-static struct rpmpd mx_rwmx0_vfl = {
-       .pd = { .name = "mx_vfl", },
-       .res_type = RPMPD_RWMX,
-       .res_id = 0,
-       .key = KEY_FLOOR_LEVEL,
-};
-
-static struct rpmpd mx_rwsm6_vfl = {
-       .pd = { .name = "mx_vfl", },
-       .res_type = RPMPD_RWSM,
-       .res_id = 6,
-       .key = KEY_FLOOR_LEVEL,
-};
-
-/* MD */
-static struct rpmpd md_s1a_corner_ao;
-static struct rpmpd md_s1a_corner = {
-       .pd = { .name = "md", },
-       .peer = &md_s1a_corner_ao,
-       .res_type = RPMPD_SMPA,
-       .res_id = 1,
-       .key = KEY_CORNER,
-};
-
-static struct rpmpd md_s1a_corner_ao = {
-       .pd = { .name = "md_ao", },
-       .peer = &md_s1a_corner,
-       .active_only = true,
-       .res_type = RPMPD_SMPA,
-       .res_id = 1,
-       .key = KEY_CORNER,
-};
-
-static struct rpmpd md_s1a_lvl_ao;
-static struct rpmpd md_s1a_lvl = {
-       .pd = { .name = "md", },
-       .peer = &md_s1a_lvl_ao,
-       .res_type = RPMPD_SMPA,
-       .res_id = 1,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd md_s1a_lvl_ao = {
-       .pd = { .name = "md_ao", },
-       .peer = &md_s1a_lvl,
-       .active_only = true,
-       .res_type = RPMPD_SMPA,
-       .res_id = 1,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd md_s1a_vfc = {
-       .pd = { .name = "md_vfc", },
-       .res_type = RPMPD_SMPA,
-       .res_id = 1,
-       .key = KEY_FLOOR_CORNER,
-};
-
-/* LPI_CX */
-static struct rpmpd lpi_cx_rwlc0_lvl = {
-       .pd = { .name = "lpi_cx", },
-       .res_type = RPMPD_RWLC,
-       .res_id = 0,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd lpi_cx_rwlc0_vfl = {
-       .pd = { .name = "lpi_cx_vfl", },
-       .res_type = RPMPD_RWLC,
-       .res_id = 0,
-       .key = KEY_FLOOR_LEVEL,
-};
-
-/* LPI_MX */
-static struct rpmpd lpi_mx_rwlm0_lvl = {
-       .pd = { .name = "lpi_mx", },
-       .res_type = RPMPD_RWLM,
-       .res_id = 0,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd lpi_mx_rwlm0_vfl = {
-       .pd = { .name = "lpi_mx_vfl", },
-       .res_type = RPMPD_RWLM,
-       .res_id = 0,
-       .key = KEY_FLOOR_LEVEL,
-};
-
-/* SSC_CX */
-static struct rpmpd ssc_cx_l26a_corner = {
-       .pd = { .name = "ssc_cx", },
-       .res_type = RPMPD_LDOA,
-       .res_id = 26,
-       .key = KEY_CORNER,
-};
-
-static struct rpmpd ssc_cx_rwlc0_lvl = {
-       .pd = { .name = "ssc_cx", },
-       .res_type = RPMPD_RWLC,
-       .res_id = 0,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd ssc_cx_rwsc0_lvl = {
-       .pd = { .name = "ssc_cx", },
-       .res_type = RPMPD_RWSC,
-       .res_id = 0,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd ssc_cx_l26a_vfc = {
-       .pd = { .name = "ssc_cx_vfc", },
-       .res_type = RPMPD_LDOA,
-       .res_id = 26,
-       .key = KEY_FLOOR_CORNER,
-};
-
-static struct rpmpd ssc_cx_rwlc0_vfl = {
-       .pd = { .name = "ssc_cx_vfl", },
-       .res_type = RPMPD_RWLC,
-       .res_id = 0,
-       .key = KEY_FLOOR_LEVEL,
-};
-
-static struct rpmpd ssc_cx_rwsc0_vfl = {
-       .pd = { .name = "ssc_cx_vfl", },
-       .res_type = RPMPD_RWSC,
-       .res_id = 0,
-       .key = KEY_FLOOR_LEVEL,
-};
-
-/* SSC_MX */
-static struct rpmpd ssc_mx_rwlm0_lvl = {
-       .pd = { .name = "ssc_mx", },
-       .res_type = RPMPD_RWLM,
-       .res_id = 0,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd ssc_mx_rwsm0_lvl = {
-       .pd = { .name = "ssc_mx", },
-       .res_type = RPMPD_RWSM,
-       .res_id = 0,
-       .key = KEY_LEVEL,
-};
-
-static struct rpmpd ssc_mx_rwlm0_vfl = {
-       .pd = { .name = "ssc_mx_vfl", },
-       .res_type = RPMPD_RWLM,
-       .res_id = 0,
-       .key = KEY_FLOOR_LEVEL,
-};
-
-static struct rpmpd ssc_mx_rwsm0_vfl = {
-       .pd = { .name = "ssc_mx_vfl", },
-       .res_type = RPMPD_RWSM,
-       .res_id = 0,
-       .key = KEY_FLOOR_LEVEL,
-};
-
-static struct rpmpd *mdm9607_rpmpds[] = {
-       [MDM9607_VDDCX] =       &cx_s3a_lvl,
-       [MDM9607_VDDCX_AO] =    &cx_s3a_lvl_ao,
-       [MDM9607_VDDCX_VFL] =   &cx_s3a_vfl,
-       [MDM9607_VDDMX] =       &mx_l12a_lvl,
-       [MDM9607_VDDMX_AO] =    &mx_l12a_lvl_ao,
-       [MDM9607_VDDMX_VFL] =   &mx_l12a_vfl,
-};
-
-static const struct rpmpd_desc mdm9607_desc = {
-       .rpmpds = mdm9607_rpmpds,
-       .num_pds = ARRAY_SIZE(mdm9607_rpmpds),
-       .max_state = RPM_SMD_LEVEL_TURBO,
-};
-
-static struct rpmpd *msm8226_rpmpds[] = {
-       [MSM8226_VDDCX] =       &cx_s1a_corner,
-       [MSM8226_VDDCX_AO] =    &cx_s1a_corner_ao,
-       [MSM8226_VDDCX_VFC] =   &cx_s1a_vfc,
-};
-
-static const struct rpmpd_desc msm8226_desc = {
-       .rpmpds = msm8226_rpmpds,
-       .num_pds = ARRAY_SIZE(msm8226_rpmpds),
-       .max_state = MAX_CORNER_RPMPD_STATE,
-};
-
-static struct rpmpd *msm8939_rpmpds[] = {
-       [MSM8939_VDDMDCX] =     &md_s1a_corner,
-       [MSM8939_VDDMDCX_AO] =  &md_s1a_corner_ao,
-       [MSM8939_VDDMDCX_VFC] = &md_s1a_vfc,
-       [MSM8939_VDDCX] =       &cx_s2a_corner,
-       [MSM8939_VDDCX_AO] =    &cx_s2a_corner_ao,
-       [MSM8939_VDDCX_VFC] =   &cx_s2a_vfc,
-       [MSM8939_VDDMX] =       &mx_l3a_corner,
-       [MSM8939_VDDMX_AO] =    &mx_l3a_corner_ao,
-};
-
-static const struct rpmpd_desc msm8939_desc = {
-       .rpmpds = msm8939_rpmpds,
-       .num_pds = ARRAY_SIZE(msm8939_rpmpds),
-       .max_state = MAX_CORNER_RPMPD_STATE,
-};
-
-static struct rpmpd *msm8916_rpmpds[] = {
-       [MSM8916_VDDCX] =       &cx_s1a_corner,
-       [MSM8916_VDDCX_AO] =    &cx_s1a_corner_ao,
-       [MSM8916_VDDCX_VFC] =   &cx_s1a_vfc,
-       [MSM8916_VDDMX] =       &mx_l3a_corner,
-       [MSM8916_VDDMX_AO] =    &mx_l3a_corner_ao,
-};
-
-static const struct rpmpd_desc msm8916_desc = {
-       .rpmpds = msm8916_rpmpds,
-       .num_pds = ARRAY_SIZE(msm8916_rpmpds),
-       .max_state = MAX_CORNER_RPMPD_STATE,
-};
-
-static struct rpmpd *msm8953_rpmpds[] = {
-       [MSM8953_VDDMD] =       &md_s1a_lvl,
-       [MSM8953_VDDMD_AO] =    &md_s1a_lvl_ao,
-       [MSM8953_VDDCX] =       &cx_s2a_lvl,
-       [MSM8953_VDDCX_AO] =    &cx_s2a_lvl_ao,
-       [MSM8953_VDDCX_VFL] =   &cx_s2a_vfl,
-       [MSM8953_VDDMX] =       &mx_s7a_lvl,
-       [MSM8953_VDDMX_AO] =    &mx_s7a_lvl_ao,
-};
-
-static const struct rpmpd_desc msm8953_desc = {
-       .rpmpds = msm8953_rpmpds,
-       .num_pds = ARRAY_SIZE(msm8953_rpmpds),
-       .max_state = RPM_SMD_LEVEL_TURBO,
-};
-
-static struct rpmpd *msm8976_rpmpds[] = {
-       [MSM8976_VDDCX] =       &cx_s2a_lvl,
-       [MSM8976_VDDCX_AO] =    &cx_s2a_lvl_ao,
-       [MSM8976_VDDCX_VFL] =   &cx_rwsc2_vfl,
-       [MSM8976_VDDMX] =       &mx_s6a_lvl,
-       [MSM8976_VDDMX_AO] =    &mx_s6a_lvl_ao,
-       [MSM8976_VDDMX_VFL] =   &mx_rwsm6_vfl,
-};
-
-static const struct rpmpd_desc msm8976_desc = {
-       .rpmpds = msm8976_rpmpds,
-       .num_pds = ARRAY_SIZE(msm8976_rpmpds),
-       .max_state = RPM_SMD_LEVEL_TURBO_HIGH,
-};
-
-static struct rpmpd *msm8994_rpmpds[] = {
-       [MSM8994_VDDCX] =       &cx_s1a_corner,
-       [MSM8994_VDDCX_AO] =    &cx_s1a_corner_ao,
-       [MSM8994_VDDCX_VFC] =   &cx_s1a_vfc,
-       [MSM8994_VDDMX] =       &mx_s2a_corner,
-       [MSM8994_VDDMX_AO] =    &mx_s2a_corner_ao,
-
-       /* Attention! *Some* 8994 boards with pm8004 may use SMPC here! */
-       [MSM8994_VDDGFX] =      &gfx_s2b_corner,
-       [MSM8994_VDDGFX_VFC] =  &gfx_s2b_vfc,
-};
-
-static const struct rpmpd_desc msm8994_desc = {
-       .rpmpds = msm8994_rpmpds,
-       .num_pds = ARRAY_SIZE(msm8994_rpmpds),
-       .max_state = MAX_CORNER_RPMPD_STATE,
-};
-
-static struct rpmpd *msm8996_rpmpds[] = {
-       [MSM8996_VDDCX] =       &cx_s1a_corner,
-       [MSM8996_VDDCX_AO] =    &cx_s1a_corner_ao,
-       [MSM8996_VDDCX_VFC] =   &cx_s1a_vfc,
-       [MSM8996_VDDMX] =       &mx_s2a_corner,
-       [MSM8996_VDDMX_AO] =    &mx_s2a_corner_ao,
-       [MSM8996_VDDSSCX] =     &ssc_cx_l26a_corner,
-       [MSM8996_VDDSSCX_VFC] = &ssc_cx_l26a_vfc,
-};
-
-static const struct rpmpd_desc msm8996_desc = {
-       .rpmpds = msm8996_rpmpds,
-       .num_pds = ARRAY_SIZE(msm8996_rpmpds),
-       .max_state = MAX_CORNER_RPMPD_STATE,
-};
-
-static struct rpmpd *msm8998_rpmpds[] = {
-       [MSM8998_VDDCX] =       &cx_rwcx0_lvl,
-       [MSM8998_VDDCX_AO] =    &cx_rwcx0_lvl_ao,
-       [MSM8998_VDDCX_VFL] =   &cx_rwcx0_vfl,
-       [MSM8998_VDDMX] =       &mx_rwmx0_lvl,
-       [MSM8998_VDDMX_AO] =    &mx_rwmx0_lvl_ao,
-       [MSM8998_VDDMX_VFL] =   &mx_rwmx0_vfl,
-       [MSM8998_SSCCX] =       &ssc_cx_rwsc0_lvl,
-       [MSM8998_SSCCX_VFL] =   &ssc_cx_rwsc0_vfl,
-       [MSM8998_SSCMX] =       &ssc_mx_rwsm0_lvl,
-       [MSM8998_SSCMX_VFL] =   &ssc_mx_rwsm0_vfl,
-};
-
-static const struct rpmpd_desc msm8998_desc = {
-       .rpmpds = msm8998_rpmpds,
-       .num_pds = ARRAY_SIZE(msm8998_rpmpds),
-       .max_state = RPM_SMD_LEVEL_BINNING,
-};
-
-static struct rpmpd *qcs404_rpmpds[] = {
-       [QCS404_VDDMX] =        &mx_rwmx0_lvl,
-       [QCS404_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
-       [QCS404_VDDMX_VFL] =    &mx_rwmx0_vfl,
-       [QCS404_LPICX] =        &lpi_cx_rwlc0_lvl,
-       [QCS404_LPICX_VFL] =    &lpi_cx_rwlc0_vfl,
-       [QCS404_LPIMX] =        &lpi_mx_rwlm0_lvl,
-       [QCS404_LPIMX_VFL] =    &lpi_mx_rwlm0_vfl,
-};
-
-static const struct rpmpd_desc qcs404_desc = {
-       .rpmpds = qcs404_rpmpds,
-       .num_pds = ARRAY_SIZE(qcs404_rpmpds),
-       .max_state = RPM_SMD_LEVEL_BINNING,
-};
-
-static struct rpmpd *sdm660_rpmpds[] = {
-       [SDM660_VDDCX] =        &cx_rwcx0_lvl,
-       [SDM660_VDDCX_AO] =     &cx_rwcx0_lvl_ao,
-       [SDM660_VDDCX_VFL] =    &cx_rwcx0_vfl,
-       [SDM660_VDDMX] =        &mx_rwmx0_lvl,
-       [SDM660_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
-       [SDM660_VDDMX_VFL] =    &mx_rwmx0_vfl,
-       [SDM660_SSCCX] =        &ssc_cx_rwlc0_lvl,
-       [SDM660_SSCCX_VFL] =    &ssc_cx_rwlc0_vfl,
-       [SDM660_SSCMX] =        &ssc_mx_rwlm0_lvl,
-       [SDM660_SSCMX_VFL] =    &ssc_mx_rwlm0_vfl,
-};
-
-static const struct rpmpd_desc sdm660_desc = {
-       .rpmpds = sdm660_rpmpds,
-       .num_pds = ARRAY_SIZE(sdm660_rpmpds),
-       .max_state = RPM_SMD_LEVEL_TURBO,
-};
-
-static struct rpmpd *sm6115_rpmpds[] = {
-       [SM6115_VDDCX] =        &cx_rwcx0_lvl,
-       [SM6115_VDDCX_AO] =     &cx_rwcx0_lvl_ao,
-       [SM6115_VDDCX_VFL] =    &cx_rwcx0_vfl,
-       [SM6115_VDDMX] =        &mx_rwmx0_lvl,
-       [SM6115_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
-       [SM6115_VDDMX_VFL] =    &mx_rwmx0_vfl,
-       [SM6115_VDD_LPI_CX] =   &lpi_cx_rwlc0_lvl,
-       [SM6115_VDD_LPI_MX] =   &lpi_mx_rwlm0_lvl,
-};
-
-static const struct rpmpd_desc sm6115_desc = {
-       .rpmpds = sm6115_rpmpds,
-       .num_pds = ARRAY_SIZE(sm6115_rpmpds),
-       .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
-};
-
-static struct rpmpd *sm6125_rpmpds[] = {
-       [SM6125_VDDCX] =        &cx_rwcx0_lvl,
-       [SM6125_VDDCX_AO] =     &cx_rwcx0_lvl_ao,
-       [SM6125_VDDCX_VFL] =    &cx_rwcx0_vfl,
-       [SM6125_VDDMX] =        &mx_rwmx0_lvl,
-       [SM6125_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
-       [SM6125_VDDMX_VFL] =    &mx_rwmx0_vfl,
-};
-
-static const struct rpmpd_desc sm6125_desc = {
-       .rpmpds = sm6125_rpmpds,
-       .num_pds = ARRAY_SIZE(sm6125_rpmpds),
-       .max_state = RPM_SMD_LEVEL_BINNING,
-};
-
-static struct rpmpd *sm6375_rpmpds[] = {
-       [SM6375_VDDCX] =        &cx_rwcx0_lvl,
-       [SM6375_VDDCX_AO] =     &cx_rwcx0_lvl_ao,
-       [SM6375_VDDCX_VFL] =    &cx_rwcx0_vfl,
-       [SM6375_VDDMX] =        &mx_rwmx0_lvl,
-       [SM6375_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
-       [SM6375_VDDMX_VFL] =    &mx_rwmx0_vfl,
-       [SM6375_VDDGX] =        &gx_rwgx0_lvl,
-       [SM6375_VDDGX_AO] =     &gx_rwgx0_lvl_ao,
-       [SM6375_VDD_LPI_CX] =   &lpi_cx_rwlc0_lvl,
-       [SM6375_VDD_LPI_MX] =   &lpi_mx_rwlm0_lvl,
-};
-
-static const struct rpmpd_desc sm6375_desc = {
-       .rpmpds = sm6375_rpmpds,
-       .num_pds = ARRAY_SIZE(sm6375_rpmpds),
-       .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
-};
-
-static struct rpmpd *qcm2290_rpmpds[] = {
-       [QCM2290_VDDCX] =       &cx_rwcx0_lvl,
-       [QCM2290_VDDCX_AO] =    &cx_rwcx0_lvl_ao,
-       [QCM2290_VDDCX_VFL] =   &cx_rwcx0_vfl,
-       [QCM2290_VDDMX] =       &mx_rwmx0_lvl,
-       [QCM2290_VDDMX_AO] =    &mx_rwmx0_lvl_ao,
-       [QCM2290_VDDMX_VFL] =   &mx_rwmx0_vfl,
-       [QCM2290_VDD_LPI_CX] =  &lpi_cx_rwlc0_lvl,
-       [QCM2290_VDD_LPI_MX] =  &lpi_mx_rwlm0_lvl,
-};
-
-static const struct rpmpd_desc qcm2290_desc = {
-       .rpmpds = qcm2290_rpmpds,
-       .num_pds = ARRAY_SIZE(qcm2290_rpmpds),
-       .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
-};
-
-static const struct of_device_id rpmpd_match_table[] = {
-       { .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc },
-       { .compatible = "qcom,msm8226-rpmpd", .data = &msm8226_desc },
-       { .compatible = "qcom,msm8909-rpmpd", .data = &msm8916_desc },
-       { .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
-       { .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc },
-       { .compatible = "qcom,msm8953-rpmpd", .data = &msm8953_desc },
-       { .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
-       { .compatible = "qcom,msm8994-rpmpd", .data = &msm8994_desc },
-       { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
-       { .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
-       { .compatible = "qcom,qcm2290-rpmpd", .data = &qcm2290_desc },
-       { .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc },
-       { .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc },
-       { .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc },
-       { .compatible = "qcom,sm6125-rpmpd", .data = &sm6125_desc },
-       { .compatible = "qcom,sm6375-rpmpd", .data = &sm6375_desc },
-       { }
-};
-MODULE_DEVICE_TABLE(of, rpmpd_match_table);
-
-static int rpmpd_send_enable(struct rpmpd *pd, bool enable)
-{
-       struct rpmpd_req req = {
-               .key = KEY_ENABLE,
-               .nbytes = cpu_to_le32(sizeof(u32)),
-               .value = cpu_to_le32(enable),
-       };
-
-       return qcom_rpm_smd_write(pd->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
-                                 pd->res_type, pd->res_id, &req, sizeof(req));
-}
-
-static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner)
-{
-       struct rpmpd_req req = {
-               .key = pd->key,
-               .nbytes = cpu_to_le32(sizeof(u32)),
-               .value = cpu_to_le32(corner),
-       };
-
-       return qcom_rpm_smd_write(pd->rpm, state, pd->res_type, pd->res_id,
-                                 &req, sizeof(req));
-};
-
-static void to_active_sleep(struct rpmpd *pd, unsigned int corner,
-                           unsigned int *active, unsigned int *sleep)
-{
-       *active = corner;
-
-       if (pd->active_only)
-               *sleep = 0;
-       else
-               *sleep = *active;
-}
-
-static int rpmpd_aggregate_corner(struct rpmpd *pd)
-{
-       int ret;
-       struct rpmpd *peer = pd->peer;
-       unsigned int active_corner, sleep_corner;
-       unsigned int this_active_corner = 0, this_sleep_corner = 0;
-       unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
-
-       /* Clamp to the highest corner/level if sync_state isn't done yet */
-       if (!pd->state_synced)
-               this_active_corner = this_sleep_corner = pd->max_state - 1;
-       else
-               to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner);
-
-       if (peer && peer->enabled)
-               to_active_sleep(peer, peer->corner, &peer_active_corner,
-                               &peer_sleep_corner);
-
-       active_corner = max(this_active_corner, peer_active_corner);
-
-       ret = rpmpd_send_corner(pd, QCOM_SMD_RPM_ACTIVE_STATE, active_corner);
-       if (ret)
-               return ret;
-
-       sleep_corner = max(this_sleep_corner, peer_sleep_corner);
-
-       return rpmpd_send_corner(pd, QCOM_SMD_RPM_SLEEP_STATE, sleep_corner);
-}
-
-static int rpmpd_power_on(struct generic_pm_domain *domain)
-{
-       int ret;
-       struct rpmpd *pd = domain_to_rpmpd(domain);
-
-       mutex_lock(&rpmpd_lock);
-
-       ret = rpmpd_send_enable(pd, true);
-       if (ret)
-               goto out;
-
-       pd->enabled = true;
-
-       if (pd->corner)
-               ret = rpmpd_aggregate_corner(pd);
-
-out:
-       mutex_unlock(&rpmpd_lock);
-
-       return ret;
-}
-
-static int rpmpd_power_off(struct generic_pm_domain *domain)
-{
-       int ret;
-       struct rpmpd *pd = domain_to_rpmpd(domain);
-
-       mutex_lock(&rpmpd_lock);
-
-       ret = rpmpd_send_enable(pd, false);
-       if (!ret)
-               pd->enabled = false;
-
-       mutex_unlock(&rpmpd_lock);
-
-       return ret;
-}
-
-static int rpmpd_set_performance(struct generic_pm_domain *domain,
-                                unsigned int state)
-{
-       int ret = 0;
-       struct rpmpd *pd = domain_to_rpmpd(domain);
-
-       if (state > pd->max_state)
-               state = pd->max_state;
-
-       mutex_lock(&rpmpd_lock);
-
-       pd->corner = state;
-
-       /* Always send updates for vfc and vfl */
-       if (!pd->enabled && pd->key != cpu_to_le32(KEY_FLOOR_CORNER) &&
-           pd->key != cpu_to_le32(KEY_FLOOR_LEVEL))
-               goto out;
-
-       ret = rpmpd_aggregate_corner(pd);
-
-out:
-       mutex_unlock(&rpmpd_lock);
-
-       return ret;
-}
-
-static unsigned int rpmpd_get_performance(struct generic_pm_domain *genpd,
-                                         struct dev_pm_opp *opp)
-{
-       return dev_pm_opp_get_level(opp);
-}
-
-static int rpmpd_probe(struct platform_device *pdev)
-{
-       int i;
-       size_t num;
-       struct genpd_onecell_data *data;
-       struct qcom_smd_rpm *rpm;
-       struct rpmpd **rpmpds;
-       const struct rpmpd_desc *desc;
-
-       rpm = dev_get_drvdata(pdev->dev.parent);
-       if (!rpm) {
-               dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
-               return -ENODEV;
-       }
-
-       desc = of_device_get_match_data(&pdev->dev);
-       if (!desc)
-               return -EINVAL;
-
-       rpmpds = desc->rpmpds;
-       num = desc->num_pds;
-
-       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains),
-                                    GFP_KERNEL);
-       if (!data->domains)
-               return -ENOMEM;
-
-       data->num_domains = num;
-
-       for (i = 0; i < num; i++) {
-               if (!rpmpds[i]) {
-                       dev_warn(&pdev->dev, "rpmpds[] with empty entry at index=%d\n",
-                                i);
-                       continue;
-               }
-
-               rpmpds[i]->rpm = rpm;
-               rpmpds[i]->max_state = desc->max_state;
-               rpmpds[i]->pd.power_off = rpmpd_power_off;
-               rpmpds[i]->pd.power_on = rpmpd_power_on;
-               rpmpds[i]->pd.set_performance_state = rpmpd_set_performance;
-               rpmpds[i]->pd.opp_to_performance_state = rpmpd_get_performance;
-               pm_genpd_init(&rpmpds[i]->pd, NULL, true);
-
-               data->domains[i] = &rpmpds[i]->pd;
-       }
-
-       /* Add subdomains */
-       for (i = 0; i < num; i++) {
-               if (!rpmpds[i])
-                       continue;
-
-               if (rpmpds[i]->parent)
-                       pm_genpd_add_subdomain(rpmpds[i]->parent, &rpmpds[i]->pd);
-       }
-
-       return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
-}
-
-static void rpmpd_sync_state(struct device *dev)
-{
-       const struct rpmpd_desc *desc = of_device_get_match_data(dev);
-       struct rpmpd **rpmpds = desc->rpmpds;
-       struct rpmpd *pd;
-       unsigned int i;
-       int ret;
-
-       mutex_lock(&rpmpd_lock);
-       for (i = 0; i < desc->num_pds; i++) {
-               pd = rpmpds[i];
-               if (!pd)
-                       continue;
-
-               pd->state_synced = true;
-
-               if (!pd->enabled)
-                       pd->corner = 0;
-
-               ret = rpmpd_aggregate_corner(pd);
-               if (ret)
-                       dev_err(dev, "failed to sync %s: %d\n", pd->pd.name, ret);
-       }
-       mutex_unlock(&rpmpd_lock);
-}
-
-static struct platform_driver rpmpd_driver = {
-       .driver = {
-               .name = "qcom-rpmpd",
-               .of_match_table = rpmpd_match_table,
-               .suppress_bind_attrs = true,
-               .sync_state = rpmpd_sync_state,
-       },
-       .probe = rpmpd_probe,
-};
-
-static int __init rpmpd_init(void)
-{
-       return platform_driver_register(&rpmpd_driver);
-}
-core_initcall(rpmpd_init);
-
-MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPM Power Domain Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/genpd/renesas/Makefile b/drivers/genpd/renesas/Makefile
deleted file mode 100644 (file)
index e306e39..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# SoC
-obj-$(CONFIG_SYSC_R8A7742)     += r8a7742-sysc.o
-obj-$(CONFIG_SYSC_R8A7743)     += r8a7743-sysc.o
-obj-$(CONFIG_SYSC_R8A7745)     += r8a7745-sysc.o
-obj-$(CONFIG_SYSC_R8A77470)    += r8a77470-sysc.o
-obj-$(CONFIG_SYSC_R8A774A1)    += r8a774a1-sysc.o
-obj-$(CONFIG_SYSC_R8A774B1)    += r8a774b1-sysc.o
-obj-$(CONFIG_SYSC_R8A774C0)    += r8a774c0-sysc.o
-obj-$(CONFIG_SYSC_R8A774E1)    += r8a774e1-sysc.o
-obj-$(CONFIG_SYSC_R8A7779)     += r8a7779-sysc.o
-obj-$(CONFIG_SYSC_R8A7790)     += r8a7790-sysc.o
-obj-$(CONFIG_SYSC_R8A7791)     += r8a7791-sysc.o
-obj-$(CONFIG_SYSC_R8A7792)     += r8a7792-sysc.o
-obj-$(CONFIG_SYSC_R8A7794)     += r8a7794-sysc.o
-obj-$(CONFIG_SYSC_R8A7795)     += r8a7795-sysc.o
-obj-$(CONFIG_SYSC_R8A77960)    += r8a7796-sysc.o
-obj-$(CONFIG_SYSC_R8A77961)    += r8a7796-sysc.o
-obj-$(CONFIG_SYSC_R8A77965)    += r8a77965-sysc.o
-obj-$(CONFIG_SYSC_R8A77970)    += r8a77970-sysc.o
-obj-$(CONFIG_SYSC_R8A77980)    += r8a77980-sysc.o
-obj-$(CONFIG_SYSC_R8A77990)    += r8a77990-sysc.o
-obj-$(CONFIG_SYSC_R8A77995)    += r8a77995-sysc.o
-obj-$(CONFIG_SYSC_R8A779A0)    += r8a779a0-sysc.o
-obj-$(CONFIG_SYSC_R8A779F0)    += r8a779f0-sysc.o
-obj-$(CONFIG_SYSC_R8A779G0)    += r8a779g0-sysc.o
-# Family
-obj-$(CONFIG_SYSC_RCAR)                += rcar-sysc.o
-obj-$(CONFIG_SYSC_RCAR_GEN4)   += rcar-gen4-sysc.o
-obj-$(CONFIG_SYSC_RMOBILE)     += rmobile-sysc.o
diff --git a/drivers/genpd/renesas/r8a7742-sysc.c b/drivers/genpd/renesas/r8a7742-sysc.c
deleted file mode 100644 (file)
index 219a675..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas RZ/G1H System Controller
- *
- * Copyright (C) 2020 Renesas Electronics Corp.
- */
-
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a7742-sysc.h>
-
-#include "rcar-sysc.h"
-
-static const struct rcar_sysc_area r8a7742_areas[] __initconst = {
-       { "always-on",      0, 0, R8A7742_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca15-scu",   0x180, 0, R8A7742_PD_CA15_SCU,  R8A7742_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca15-cpu0",   0x40, 0, R8A7742_PD_CA15_CPU0, R8A7742_PD_CA15_SCU,
-         PD_CPU_NOCR },
-       { "ca15-cpu1",   0x40, 1, R8A7742_PD_CA15_CPU1, R8A7742_PD_CA15_SCU,
-         PD_CPU_NOCR },
-       { "ca15-cpu2",   0x40, 2, R8A7742_PD_CA15_CPU2, R8A7742_PD_CA15_SCU,
-         PD_CPU_NOCR },
-       { "ca15-cpu3",   0x40, 3, R8A7742_PD_CA15_CPU3, R8A7742_PD_CA15_SCU,
-         PD_CPU_NOCR },
-       { "ca7-scu",    0x100, 0, R8A7742_PD_CA7_SCU,   R8A7742_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca7-cpu0",   0x1c0, 0, R8A7742_PD_CA7_CPU0,  R8A7742_PD_CA7_SCU,
-         PD_CPU_NOCR },
-       { "ca7-cpu1",   0x1c0, 1, R8A7742_PD_CA7_CPU1,  R8A7742_PD_CA7_SCU,
-         PD_CPU_NOCR },
-       { "ca7-cpu2",   0x1c0, 2, R8A7742_PD_CA7_CPU2,  R8A7742_PD_CA7_SCU,
-         PD_CPU_NOCR },
-       { "ca7-cpu3",   0x1c0, 3, R8A7742_PD_CA7_CPU3,  R8A7742_PD_CA7_SCU,
-         PD_CPU_NOCR },
-       { "rgx",         0xc0, 0, R8A7742_PD_RGX,       R8A7742_PD_ALWAYS_ON },
-};
-
-const struct rcar_sysc_info r8a7742_sysc_info __initconst = {
-       .areas = r8a7742_areas,
-       .num_areas = ARRAY_SIZE(r8a7742_areas),
-};
diff --git a/drivers/genpd/renesas/r8a7743-sysc.c b/drivers/genpd/renesas/r8a7743-sysc.c
deleted file mode 100644 (file)
index 4e2c0ab..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas RZ/G1M System Controller
- *
- * Copyright (C) 2016 Cogent Embedded Inc.
- */
-
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a7743-sysc.h>
-
-#include "rcar-sysc.h"
-
-static const struct rcar_sysc_area r8a7743_areas[] __initconst = {
-       { "always-on",      0, 0, R8A7743_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca15-scu",   0x180, 0, R8A7743_PD_CA15_SCU,  R8A7743_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca15-cpu0",   0x40, 0, R8A7743_PD_CA15_CPU0, R8A7743_PD_CA15_SCU,
-         PD_CPU_NOCR },
-       { "ca15-cpu1",   0x40, 1, R8A7743_PD_CA15_CPU1, R8A7743_PD_CA15_SCU,
-         PD_CPU_NOCR },
-       { "sgx",         0xc0, 0, R8A7743_PD_SGX,       R8A7743_PD_ALWAYS_ON },
-};
-
-const struct rcar_sysc_info r8a7743_sysc_info __initconst = {
-       .areas = r8a7743_areas,
-       .num_areas = ARRAY_SIZE(r8a7743_areas),
-};
diff --git a/drivers/genpd/renesas/r8a7745-sysc.c b/drivers/genpd/renesas/r8a7745-sysc.c
deleted file mode 100644 (file)
index 865821a..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas RZ/G1E System Controller
- *
- * Copyright (C) 2016 Cogent Embedded Inc.
- */
-
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a7745-sysc.h>
-
-#include "rcar-sysc.h"
-
-static const struct rcar_sysc_area r8a7745_areas[] __initconst = {
-       { "always-on",      0, 0, R8A7745_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca7-scu",    0x100, 0, R8A7745_PD_CA7_SCU,   R8A7745_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca7-cpu0",   0x1c0, 0, R8A7745_PD_CA7_CPU0,  R8A7745_PD_CA7_SCU,
-         PD_CPU_NOCR },
-       { "ca7-cpu1",   0x1c0, 1, R8A7745_PD_CA7_CPU1,  R8A7745_PD_CA7_SCU,
-         PD_CPU_NOCR },
-       { "sgx",         0xc0, 0, R8A7745_PD_SGX,       R8A7745_PD_ALWAYS_ON },
-};
-
-const struct rcar_sysc_info r8a7745_sysc_info __initconst = {
-       .areas = r8a7745_areas,
-       .num_areas = ARRAY_SIZE(r8a7745_areas),
-};
diff --git a/drivers/genpd/renesas/r8a77470-sysc.c b/drivers/genpd/renesas/r8a77470-sysc.c
deleted file mode 100644 (file)
index 1eeb801..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas RZ/G1C System Controller
- *
- * Copyright (C) 2018 Renesas Electronics Corp.
- */
-
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a77470-sysc.h>
-
-#include "rcar-sysc.h"
-
-static const struct rcar_sysc_area r8a77470_areas[] __initconst = {
-       { "always-on",      0, 0, R8A77470_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca7-scu",    0x100, 0, R8A77470_PD_CA7_SCU,  R8A77470_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca7-cpu0",   0x1c0, 0, R8A77470_PD_CA7_CPU0, R8A77470_PD_CA7_SCU,
-         PD_CPU_NOCR },
-       { "ca7-cpu1",   0x1c0, 1, R8A77470_PD_CA7_CPU1, R8A77470_PD_CA7_SCU,
-         PD_CPU_NOCR },
-       { "sgx",         0xc0, 0, R8A77470_PD_SGX, R8A77470_PD_ALWAYS_ON },
-};
-
-const struct rcar_sysc_info r8a77470_sysc_info __initconst = {
-       .areas = r8a77470_areas,
-       .num_areas = ARRAY_SIZE(r8a77470_areas),
-};
diff --git a/drivers/genpd/renesas/r8a774a1-sysc.c b/drivers/genpd/renesas/r8a774a1-sysc.c
deleted file mode 100644 (file)
index 38ac2c6..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas RZ/G2M System Controller
- * Copyright (C) 2018 Renesas Electronics Corp.
- *
- * Based on Renesas R-Car M3-W System Controller
- * Copyright (C) 2016 Glider bvba
- */
-
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a774a1-sysc.h>
-
-#include "rcar-sysc.h"
-
-static const struct rcar_sysc_area r8a774a1_areas[] __initconst = {
-       { "always-on",      0, 0, R8A774A1_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca57-scu",   0x1c0, 0, R8A774A1_PD_CA57_SCU, R8A774A1_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca57-cpu0",   0x80, 0, R8A774A1_PD_CA57_CPU0, R8A774A1_PD_CA57_SCU,
-         PD_CPU_NOCR },
-       { "ca57-cpu1",   0x80, 1, R8A774A1_PD_CA57_CPU1, R8A774A1_PD_CA57_SCU,
-         PD_CPU_NOCR },
-       { "ca53-scu",   0x140, 0, R8A774A1_PD_CA53_SCU, R8A774A1_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca53-cpu0",  0x200, 0, R8A774A1_PD_CA53_CPU0, R8A774A1_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "ca53-cpu1",  0x200, 1, R8A774A1_PD_CA53_CPU1, R8A774A1_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "ca53-cpu2",  0x200, 2, R8A774A1_PD_CA53_CPU2, R8A774A1_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "ca53-cpu3",  0x200, 3, R8A774A1_PD_CA53_CPU3, R8A774A1_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "a3vc",       0x380, 0, R8A774A1_PD_A3VC,     R8A774A1_PD_ALWAYS_ON },
-       { "a2vc0",      0x3c0, 0, R8A774A1_PD_A2VC0,    R8A774A1_PD_A3VC },
-       { "a2vc1",      0x3c0, 1, R8A774A1_PD_A2VC1,    R8A774A1_PD_A3VC },
-       { "3dg-a",      0x100, 0, R8A774A1_PD_3DG_A,    R8A774A1_PD_ALWAYS_ON },
-       { "3dg-b",      0x100, 1, R8A774A1_PD_3DG_B,    R8A774A1_PD_3DG_A },
-};
-
-const struct rcar_sysc_info r8a774a1_sysc_info __initconst = {
-       .areas = r8a774a1_areas,
-       .num_areas = ARRAY_SIZE(r8a774a1_areas),
-};
diff --git a/drivers/genpd/renesas/r8a774b1-sysc.c b/drivers/genpd/renesas/r8a774b1-sysc.c
deleted file mode 100644 (file)
index 5f97ff2..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas RZ/G2N System Controller
- * Copyright (C) 2019 Renesas Electronics Corp.
- *
- * Based on Renesas R-Car M3-W System Controller
- * Copyright (C) 2016 Glider bvba
- */
-
-#include <linux/bits.h>
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a774b1-sysc.h>
-
-#include "rcar-sysc.h"
-
-static const struct rcar_sysc_area r8a774b1_areas[] __initconst = {
-       { "always-on",      0, 0, R8A774B1_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca57-scu",   0x1c0, 0, R8A774B1_PD_CA57_SCU, R8A774B1_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca57-cpu0",   0x80, 0, R8A774B1_PD_CA57_CPU0, R8A774B1_PD_CA57_SCU,
-         PD_CPU_NOCR },
-       { "ca57-cpu1",   0x80, 1, R8A774B1_PD_CA57_CPU1, R8A774B1_PD_CA57_SCU,
-         PD_CPU_NOCR },
-       { "a3vc",       0x380, 0, R8A774B1_PD_A3VC,     R8A774B1_PD_ALWAYS_ON },
-       { "a3vp",       0x340, 0, R8A774B1_PD_A3VP,     R8A774B1_PD_ALWAYS_ON },
-       { "a2vc1",      0x3c0, 1, R8A774B1_PD_A2VC1,    R8A774B1_PD_A3VC },
-       { "3dg-a",      0x100, 0, R8A774B1_PD_3DG_A,    R8A774B1_PD_ALWAYS_ON },
-       { "3dg-b",      0x100, 1, R8A774B1_PD_3DG_B,    R8A774B1_PD_3DG_A },
-};
-
-const struct rcar_sysc_info r8a774b1_sysc_info __initconst = {
-       .areas = r8a774b1_areas,
-       .num_areas = ARRAY_SIZE(r8a774b1_areas),
-       .extmask_offs = 0x2f8,
-       .extmask_val = BIT(0),
-};
diff --git a/drivers/genpd/renesas/r8a774c0-sysc.c b/drivers/genpd/renesas/r8a774c0-sysc.c
deleted file mode 100644 (file)
index c1c216f..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas RZ/G2E System Controller
- * Copyright (C) 2018 Renesas Electronics Corp.
- *
- * Based on Renesas R-Car E3 System Controller
- */
-
-#include <linux/bits.h>
-#include <linux/kernel.h>
-#include <linux/sys_soc.h>
-
-#include <dt-bindings/power/r8a774c0-sysc.h>
-
-#include "rcar-sysc.h"
-
-static struct rcar_sysc_area r8a774c0_areas[] __initdata = {
-       { "always-on",      0, 0, R8A774C0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca53-scu",   0x140, 0, R8A774C0_PD_CA53_SCU,  R8A774C0_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca53-cpu0",  0x200, 0, R8A774C0_PD_CA53_CPU0, R8A774C0_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "ca53-cpu1",  0x200, 1, R8A774C0_PD_CA53_CPU1, R8A774C0_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "a3vc",       0x380, 0, R8A774C0_PD_A3VC,     R8A774C0_PD_ALWAYS_ON },
-       { "a2vc1",      0x3c0, 1, R8A774C0_PD_A2VC1,    R8A774C0_PD_A3VC },
-       { "3dg-a",      0x100, 0, R8A774C0_PD_3DG_A,    R8A774C0_PD_ALWAYS_ON },
-       { "3dg-b",      0x100, 1, R8A774C0_PD_3DG_B,    R8A774C0_PD_3DG_A },
-};
-
-/* Fixups for RZ/G2E ES1.0 revision */
-static const struct soc_device_attribute r8a774c0[] __initconst = {
-       { .soc_id = "r8a774c0", .revision = "ES1.0" },
-       { /* sentinel */ }
-};
-
-static int __init r8a774c0_sysc_init(void)
-{
-       if (soc_device_match(r8a774c0)) {
-               /* Fix incorrect 3DG hierarchy */
-               swap(r8a774c0_areas[6], r8a774c0_areas[7]);
-               r8a774c0_areas[6].parent = R8A774C0_PD_ALWAYS_ON;
-               r8a774c0_areas[7].parent = R8A774C0_PD_3DG_B;
-       }
-
-       return 0;
-}
-
-const struct rcar_sysc_info r8a774c0_sysc_info __initconst = {
-       .init = r8a774c0_sysc_init,
-       .areas = r8a774c0_areas,
-       .num_areas = ARRAY_SIZE(r8a774c0_areas),
-       .extmask_offs = 0x2f8,
-       .extmask_val = BIT(0),
-};
diff --git a/drivers/genpd/renesas/r8a774e1-sysc.c b/drivers/genpd/renesas/r8a774e1-sysc.c
deleted file mode 100644 (file)
index 18449f7..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas RZ/G2H System Controller
- * Copyright (C) 2020 Renesas Electronics Corp.
- *
- * Based on Renesas R-Car H3 System Controller
- * Copyright (C) 2016-2017 Glider bvba
- */
-
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a774e1-sysc.h>
-
-#include "rcar-sysc.h"
-
-static const struct rcar_sysc_area r8a774e1_areas[] __initconst = {
-       { "always-on",      0, 0, R8A774E1_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca57-scu",   0x1c0, 0, R8A774E1_PD_CA57_SCU, R8A774E1_PD_ALWAYS_ON, PD_SCU },
-       { "ca57-cpu0",   0x80, 0, R8A774E1_PD_CA57_CPU0, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR },
-       { "ca57-cpu1",   0x80, 1, R8A774E1_PD_CA57_CPU1, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR },
-       { "ca57-cpu2",   0x80, 2, R8A774E1_PD_CA57_CPU2, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR },
-       { "ca57-cpu3",   0x80, 3, R8A774E1_PD_CA57_CPU3, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR },
-       { "ca53-scu",   0x140, 0, R8A774E1_PD_CA53_SCU, R8A774E1_PD_ALWAYS_ON, PD_SCU },
-       { "ca53-cpu0",  0x200, 0, R8A774E1_PD_CA53_CPU0, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR },
-       { "ca53-cpu1",  0x200, 1, R8A774E1_PD_CA53_CPU1, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR },
-       { "ca53-cpu2",  0x200, 2, R8A774E1_PD_CA53_CPU2, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR },
-       { "ca53-cpu3",  0x200, 3, R8A774E1_PD_CA53_CPU3, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR },
-       { "a3vp",       0x340, 0, R8A774E1_PD_A3VP, R8A774E1_PD_ALWAYS_ON },
-       { "a3vc",       0x380, 0, R8A774E1_PD_A3VC, R8A774E1_PD_ALWAYS_ON },
-       { "a2vc1",      0x3c0, 1, R8A774E1_PD_A2VC1, R8A774E1_PD_A3VC },
-       { "3dg-a",      0x100, 0, R8A774E1_PD_3DG_A, R8A774E1_PD_ALWAYS_ON },
-       { "3dg-b",      0x100, 1, R8A774E1_PD_3DG_B, R8A774E1_PD_3DG_A },
-       { "3dg-c",      0x100, 2, R8A774E1_PD_3DG_C, R8A774E1_PD_3DG_B },
-       { "3dg-d",      0x100, 3, R8A774E1_PD_3DG_D, R8A774E1_PD_3DG_C },
-       { "3dg-e",      0x100, 4, R8A774E1_PD_3DG_E, R8A774E1_PD_3DG_D },
-};
-
-const struct rcar_sysc_info r8a774e1_sysc_info __initconst = {
-       .areas = r8a774e1_areas,
-       .num_areas = ARRAY_SIZE(r8a774e1_areas),
-       .extmask_offs = 0x2f8,
-       .extmask_val = BIT(0),
-};
diff --git a/drivers/genpd/renesas/r8a7779-sysc.c b/drivers/genpd/renesas/r8a7779-sysc.c
deleted file mode 100644 (file)
index e24a715..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas R-Car H1 System Controller
- *
- * Copyright (C) 2016 Glider bvba
- */
-
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a7779-sysc.h>
-
-#include "rcar-sysc.h"
-
-static const struct rcar_sysc_area r8a7779_areas[] __initconst = {
-       { "always-on",      0, 0, R8A7779_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "arm1",        0x40, 1, R8A7779_PD_ARM1,      R8A7779_PD_ALWAYS_ON,
-         PD_CPU_CR },
-       { "arm2",        0x40, 2, R8A7779_PD_ARM2,      R8A7779_PD_ALWAYS_ON,
-         PD_CPU_CR },
-       { "arm3",        0x40, 3, R8A7779_PD_ARM3,      R8A7779_PD_ALWAYS_ON,
-         PD_CPU_CR },
-       { "sgx",         0xc0, 0, R8A7779_PD_SGX,       R8A7779_PD_ALWAYS_ON },
-       { "vdp",        0x100, 0, R8A7779_PD_VDP,       R8A7779_PD_ALWAYS_ON },
-       { "imp",        0x140, 0, R8A7779_PD_IMP,       R8A7779_PD_ALWAYS_ON },
-};
-
-const struct rcar_sysc_info r8a7779_sysc_info __initconst = {
-       .areas = r8a7779_areas,
-       .num_areas = ARRAY_SIZE(r8a7779_areas),
-};
diff --git a/drivers/genpd/renesas/r8a7790-sysc.c b/drivers/genpd/renesas/r8a7790-sysc.c
deleted file mode 100644 (file)
index b9afe7f..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas R-Car H2 System Controller
- *
- * Copyright (C) 2016 Glider bvba
- */
-
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a7790-sysc.h>
-
-#include "rcar-sysc.h"
-
-static const struct rcar_sysc_area r8a7790_areas[] __initconst = {
-       { "always-on",      0, 0, R8A7790_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca15-scu",   0x180, 0, R8A7790_PD_CA15_SCU,  R8A7790_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca15-cpu0",   0x40, 0, R8A7790_PD_CA15_CPU0, R8A7790_PD_CA15_SCU,
-         PD_CPU_NOCR },
-       { "ca15-cpu1",   0x40, 1, R8A7790_PD_CA15_CPU1, R8A7790_PD_CA15_SCU,
-         PD_CPU_NOCR },
-       { "ca15-cpu2",   0x40, 2, R8A7790_PD_CA15_CPU2, R8A7790_PD_CA15_SCU,
-         PD_CPU_NOCR },
-       { "ca15-cpu3",   0x40, 3, R8A7790_PD_CA15_CPU3, R8A7790_PD_CA15_SCU,
-         PD_CPU_NOCR },
-       { "ca7-scu",    0x100, 0, R8A7790_PD_CA7_SCU,   R8A7790_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca7-cpu0",   0x1c0, 0, R8A7790_PD_CA7_CPU0,  R8A7790_PD_CA7_SCU,
-         PD_CPU_NOCR },
-       { "ca7-cpu1",   0x1c0, 1, R8A7790_PD_CA7_CPU1,  R8A7790_PD_CA7_SCU,
-         PD_CPU_NOCR },
-       { "ca7-cpu2",   0x1c0, 2, R8A7790_PD_CA7_CPU2,  R8A7790_PD_CA7_SCU,
-         PD_CPU_NOCR },
-       { "ca7-cpu3",   0x1c0, 3, R8A7790_PD_CA7_CPU3,  R8A7790_PD_CA7_SCU,
-         PD_CPU_NOCR },
-       { "sh-4a",       0x80, 0, R8A7790_PD_SH_4A,     R8A7790_PD_ALWAYS_ON },
-       { "rgx",         0xc0, 0, R8A7790_PD_RGX,       R8A7790_PD_ALWAYS_ON },
-       { "imp",        0x140, 0, R8A7790_PD_IMP,       R8A7790_PD_ALWAYS_ON },
-};
-
-const struct rcar_sysc_info r8a7790_sysc_info __initconst = {
-       .areas = r8a7790_areas,
-       .num_areas = ARRAY_SIZE(r8a7790_areas),
-};
diff --git a/drivers/genpd/renesas/r8a7791-sysc.c b/drivers/genpd/renesas/r8a7791-sysc.c
deleted file mode 100644 (file)
index f00fa24..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas R-Car M2-W/N System Controller
- *
- * Copyright (C) 2016 Glider bvba
- */
-
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a7791-sysc.h>
-
-#include "rcar-sysc.h"
-
-static const struct rcar_sysc_area r8a7791_areas[] __initconst = {
-       { "always-on",      0, 0, R8A7791_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca15-scu",   0x180, 0, R8A7791_PD_CA15_SCU,  R8A7791_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca15-cpu0",   0x40, 0, R8A7791_PD_CA15_CPU0, R8A7791_PD_CA15_SCU,
-         PD_CPU_NOCR },
-       { "ca15-cpu1",   0x40, 1, R8A7791_PD_CA15_CPU1, R8A7791_PD_CA15_SCU,
-         PD_CPU_NOCR },
-       { "sh-4a",       0x80, 0, R8A7791_PD_SH_4A,     R8A7791_PD_ALWAYS_ON },
-       { "sgx",         0xc0, 0, R8A7791_PD_SGX,       R8A7791_PD_ALWAYS_ON },
-};
-
-const struct rcar_sysc_info r8a7791_sysc_info __initconst = {
-       .areas = r8a7791_areas,
-       .num_areas = ARRAY_SIZE(r8a7791_areas),
-};
diff --git a/drivers/genpd/renesas/r8a7792-sysc.c b/drivers/genpd/renesas/r8a7792-sysc.c
deleted file mode 100644 (file)
index 60aae24..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas R-Car V2H (R8A7792) System Controller
- *
- * Copyright (C) 2016 Cogent Embedded Inc.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a7792-sysc.h>
-
-#include "rcar-sysc.h"
-
-static const struct rcar_sysc_area r8a7792_areas[] __initconst = {
-       { "always-on",      0, 0, R8A7792_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca15-scu",   0x180, 0, R8A7792_PD_CA15_SCU,  R8A7792_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca15-cpu0",   0x40, 0, R8A7792_PD_CA15_CPU0, R8A7792_PD_CA15_SCU,
-         PD_CPU_NOCR },
-       { "ca15-cpu1",   0x40, 1, R8A7792_PD_CA15_CPU1, R8A7792_PD_CA15_SCU,
-         PD_CPU_NOCR },
-       { "sgx",         0xc0, 0, R8A7792_PD_SGX,       R8A7792_PD_ALWAYS_ON },
-       { "imp",        0x140, 0, R8A7792_PD_IMP,       R8A7792_PD_ALWAYS_ON },
-};
-
-const struct rcar_sysc_info r8a7792_sysc_info __initconst = {
-       .areas = r8a7792_areas,
-       .num_areas = ARRAY_SIZE(r8a7792_areas),
-};
diff --git a/drivers/genpd/renesas/r8a7794-sysc.c b/drivers/genpd/renesas/r8a7794-sysc.c
deleted file mode 100644 (file)
index 72ef4e8..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas R-Car E2 System Controller
- *
- * Copyright (C) 2016 Glider bvba
- */
-
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a7794-sysc.h>
-
-#include "rcar-sysc.h"
-
-static const struct rcar_sysc_area r8a7794_areas[] __initconst = {
-       { "always-on",      0, 0, R8A7794_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca7-scu",    0x100, 0, R8A7794_PD_CA7_SCU,   R8A7794_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca7-cpu0",   0x1c0, 0, R8A7794_PD_CA7_CPU0,  R8A7794_PD_CA7_SCU,
-         PD_CPU_NOCR },
-       { "ca7-cpu1",   0x1c0, 1, R8A7794_PD_CA7_CPU1,  R8A7794_PD_CA7_SCU,
-         PD_CPU_NOCR },
-       { "sh-4a",       0x80, 0, R8A7794_PD_SH_4A,     R8A7794_PD_ALWAYS_ON },
-       { "sgx",         0xc0, 0, R8A7794_PD_SGX,       R8A7794_PD_ALWAYS_ON },
-};
-
-const struct rcar_sysc_info r8a7794_sysc_info __initconst = {
-       .areas = r8a7794_areas,
-       .num_areas = ARRAY_SIZE(r8a7794_areas),
-};
diff --git a/drivers/genpd/renesas/r8a7795-sysc.c b/drivers/genpd/renesas/r8a7795-sysc.c
deleted file mode 100644 (file)
index cbe1ff0..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas R-Car H3 System Controller
- *
- * Copyright (C) 2016-2017 Glider bvba
- */
-
-#include <linux/bits.h>
-#include <linux/kernel.h>
-#include <linux/sys_soc.h>
-
-#include <dt-bindings/power/r8a7795-sysc.h>
-
-#include "rcar-sysc.h"
-
-static struct rcar_sysc_area r8a7795_areas[] __initdata = {
-       { "always-on",      0, 0, R8A7795_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca57-scu",   0x1c0, 0, R8A7795_PD_CA57_SCU,  R8A7795_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca57-cpu0",   0x80, 0, R8A7795_PD_CA57_CPU0, R8A7795_PD_CA57_SCU,
-         PD_CPU_NOCR },
-       { "ca57-cpu1",   0x80, 1, R8A7795_PD_CA57_CPU1, R8A7795_PD_CA57_SCU,
-         PD_CPU_NOCR },
-       { "ca57-cpu2",   0x80, 2, R8A7795_PD_CA57_CPU2, R8A7795_PD_CA57_SCU,
-         PD_CPU_NOCR },
-       { "ca57-cpu3",   0x80, 3, R8A7795_PD_CA57_CPU3, R8A7795_PD_CA57_SCU,
-         PD_CPU_NOCR },
-       { "ca53-scu",   0x140, 0, R8A7795_PD_CA53_SCU,  R8A7795_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca53-cpu0",  0x200, 0, R8A7795_PD_CA53_CPU0, R8A7795_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "ca53-cpu1",  0x200, 1, R8A7795_PD_CA53_CPU1, R8A7795_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "ca53-cpu2",  0x200, 2, R8A7795_PD_CA53_CPU2, R8A7795_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "ca53-cpu3",  0x200, 3, R8A7795_PD_CA53_CPU3, R8A7795_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "a3vp",       0x340, 0, R8A7795_PD_A3VP,      R8A7795_PD_ALWAYS_ON },
-       { "cr7",        0x240, 0, R8A7795_PD_CR7,       R8A7795_PD_ALWAYS_ON },
-       { "a3vc",       0x380, 0, R8A7795_PD_A3VC,      R8A7795_PD_ALWAYS_ON },
-       { "a2vc1",      0x3c0, 1, R8A7795_PD_A2VC1,     R8A7795_PD_A3VC },
-       { "3dg-a",      0x100, 0, R8A7795_PD_3DG_A,     R8A7795_PD_ALWAYS_ON },
-       { "3dg-b",      0x100, 1, R8A7795_PD_3DG_B,     R8A7795_PD_3DG_A },
-       { "3dg-c",      0x100, 2, R8A7795_PD_3DG_C,     R8A7795_PD_3DG_B },
-       { "3dg-d",      0x100, 3, R8A7795_PD_3DG_D,     R8A7795_PD_3DG_C },
-       { "3dg-e",      0x100, 4, R8A7795_PD_3DG_E,     R8A7795_PD_3DG_D },
-       { "a3ir",       0x180, 0, R8A7795_PD_A3IR,      R8A7795_PD_ALWAYS_ON },
-};
-
-
-       /*
-        * Fixups for R-Car H3 revisions
-        */
-
-#define NO_EXTMASK     BIT(1)          /* Missing SYSCEXTMASK register */
-
-static const struct soc_device_attribute r8a7795_quirks_match[] __initconst = {
-       {
-               .soc_id = "r8a7795", .revision = "ES2.*",
-               .data = (void *)(NO_EXTMASK),
-       },
-       { /* sentinel */ }
-};
-
-static int __init r8a7795_sysc_init(void)
-{
-       const struct soc_device_attribute *attr;
-       u32 quirks = 0;
-
-       attr = soc_device_match(r8a7795_quirks_match);
-       if (attr)
-               quirks = (uintptr_t)attr->data;
-
-       if (quirks & NO_EXTMASK)
-               r8a7795_sysc_info.extmask_val = 0;
-
-       return 0;
-}
-
-struct rcar_sysc_info r8a7795_sysc_info __initdata = {
-       .init = r8a7795_sysc_init,
-       .areas = r8a7795_areas,
-       .num_areas = ARRAY_SIZE(r8a7795_areas),
-       .extmask_offs = 0x2f8,
-       .extmask_val = BIT(0),
-};
diff --git a/drivers/genpd/renesas/r8a7796-sysc.c b/drivers/genpd/renesas/r8a7796-sysc.c
deleted file mode 100644 (file)
index 471bd5b..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas R-Car M3-W/W+ System Controller
- *
- * Copyright (C) 2016 Glider bvba
- * Copyright (C) 2018-2019 Renesas Electronics Corporation
- */
-
-#include <linux/bits.h>
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a7796-sysc.h>
-
-#include "rcar-sysc.h"
-
-static struct rcar_sysc_area r8a7796_areas[] __initdata = {
-       { "always-on",      0, 0, R8A7796_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca57-scu",   0x1c0, 0, R8A7796_PD_CA57_SCU,  R8A7796_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca57-cpu0",   0x80, 0, R8A7796_PD_CA57_CPU0, R8A7796_PD_CA57_SCU,
-         PD_CPU_NOCR },
-       { "ca57-cpu1",   0x80, 1, R8A7796_PD_CA57_CPU1, R8A7796_PD_CA57_SCU,
-         PD_CPU_NOCR },
-       { "ca53-scu",   0x140, 0, R8A7796_PD_CA53_SCU,  R8A7796_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca53-cpu0",  0x200, 0, R8A7796_PD_CA53_CPU0, R8A7796_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "ca53-cpu1",  0x200, 1, R8A7796_PD_CA53_CPU1, R8A7796_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "ca53-cpu2",  0x200, 2, R8A7796_PD_CA53_CPU2, R8A7796_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "ca53-cpu3",  0x200, 3, R8A7796_PD_CA53_CPU3, R8A7796_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "cr7",        0x240, 0, R8A7796_PD_CR7,       R8A7796_PD_ALWAYS_ON },
-       { "a3vc",       0x380, 0, R8A7796_PD_A3VC,      R8A7796_PD_ALWAYS_ON },
-       { "a2vc0",      0x3c0, 0, R8A7796_PD_A2VC0,     R8A7796_PD_A3VC },
-       { "a2vc1",      0x3c0, 1, R8A7796_PD_A2VC1,     R8A7796_PD_A3VC },
-       { "3dg-a",      0x100, 0, R8A7796_PD_3DG_A,     R8A7796_PD_ALWAYS_ON },
-       { "3dg-b",      0x100, 1, R8A7796_PD_3DG_B,     R8A7796_PD_3DG_A },
-       { "a3ir",       0x180, 0, R8A7796_PD_A3IR,      R8A7796_PD_ALWAYS_ON },
-};
-
-
-#ifdef CONFIG_SYSC_R8A77960
-const struct rcar_sysc_info r8a77960_sysc_info __initconst = {
-       .areas = r8a7796_areas,
-       .num_areas = ARRAY_SIZE(r8a7796_areas),
-};
-#endif /* CONFIG_SYSC_R8A77960 */
-
-#ifdef CONFIG_SYSC_R8A77961
-static int __init r8a77961_sysc_init(void)
-{
-       rcar_sysc_nullify(r8a7796_areas, ARRAY_SIZE(r8a7796_areas),
-                         R8A7796_PD_A2VC0);
-
-       return 0;
-}
-
-const struct rcar_sysc_info r8a77961_sysc_info __initconst = {
-       .init = r8a77961_sysc_init,
-       .areas = r8a7796_areas,
-       .num_areas = ARRAY_SIZE(r8a7796_areas),
-       .extmask_offs = 0x2f8,
-       .extmask_val = BIT(0),
-};
-#endif /* CONFIG_SYSC_R8A77961 */
diff --git a/drivers/genpd/renesas/r8a77965-sysc.c b/drivers/genpd/renesas/r8a77965-sysc.c
deleted file mode 100644 (file)
index ff0b0d1..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas R-Car M3-N System Controller
- * Copyright (C) 2018 Jacopo Mondi <jacopo+renesas@jmondi.org>
- *
- * Based on Renesas R-Car M3-W System Controller
- * Copyright (C) 2016 Glider bvba
- */
-
-#include <linux/bits.h>
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a77965-sysc.h>
-
-#include "rcar-sysc.h"
-
-static const struct rcar_sysc_area r8a77965_areas[] __initconst = {
-       { "always-on",      0, 0, R8A77965_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca57-scu",   0x1c0, 0, R8A77965_PD_CA57_SCU, R8A77965_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca57-cpu0",   0x80, 0, R8A77965_PD_CA57_CPU0, R8A77965_PD_CA57_SCU,
-         PD_CPU_NOCR },
-       { "ca57-cpu1",   0x80, 1, R8A77965_PD_CA57_CPU1, R8A77965_PD_CA57_SCU,
-         PD_CPU_NOCR },
-       { "cr7",        0x240, 0, R8A77965_PD_CR7,      R8A77965_PD_ALWAYS_ON },
-       { "a3vc",       0x380, 0, R8A77965_PD_A3VC,     R8A77965_PD_ALWAYS_ON },
-       { "a3vp",       0x340, 0, R8A77965_PD_A3VP,     R8A77965_PD_ALWAYS_ON },
-       { "a2vc1",      0x3c0, 1, R8A77965_PD_A2VC1,    R8A77965_PD_A3VC },
-       { "3dg-a",      0x100, 0, R8A77965_PD_3DG_A,    R8A77965_PD_ALWAYS_ON },
-       { "3dg-b",      0x100, 1, R8A77965_PD_3DG_B,    R8A77965_PD_3DG_A },
-};
-
-const struct rcar_sysc_info r8a77965_sysc_info __initconst = {
-       .areas = r8a77965_areas,
-       .num_areas = ARRAY_SIZE(r8a77965_areas),
-       .extmask_offs = 0x2f8,
-       .extmask_val = BIT(0),
-};
diff --git a/drivers/genpd/renesas/r8a77970-sysc.c b/drivers/genpd/renesas/r8a77970-sysc.c
deleted file mode 100644 (file)
index 7062582..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas R-Car V3M System Controller
- *
- * Copyright (C) 2017 Cogent Embedded Inc.
- */
-
-#include <linux/bits.h>
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a77970-sysc.h>
-
-#include "rcar-sysc.h"
-
-static const struct rcar_sysc_area r8a77970_areas[] __initconst = {
-       { "always-on",      0, 0, R8A77970_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca53-scu",   0x140, 0, R8A77970_PD_CA53_SCU, R8A77970_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca53-cpu0",  0x200, 0, R8A77970_PD_CA53_CPU0, R8A77970_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "ca53-cpu1",  0x200, 1, R8A77970_PD_CA53_CPU1, R8A77970_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "a3ir",       0x180, 0, R8A77970_PD_A3IR,     R8A77970_PD_ALWAYS_ON },
-       { "a2ir0",      0x400, 0, R8A77970_PD_A2IR0,    R8A77970_PD_A3IR },
-       { "a2ir1",      0x400, 1, R8A77970_PD_A2IR1,    R8A77970_PD_A3IR },
-       { "a2dp",       0x400, 2, R8A77970_PD_A2DP,     R8A77970_PD_A3IR },
-       { "a2cn",       0x400, 3, R8A77970_PD_A2CN,     R8A77970_PD_A3IR },
-       { "a2sc0",      0x400, 4, R8A77970_PD_A2SC0,    R8A77970_PD_A3IR },
-       { "a2sc1",      0x400, 5, R8A77970_PD_A2SC1,    R8A77970_PD_A3IR },
-};
-
-const struct rcar_sysc_info r8a77970_sysc_info __initconst = {
-       .areas = r8a77970_areas,
-       .num_areas = ARRAY_SIZE(r8a77970_areas),
-       .extmask_offs = 0x1b0,
-       .extmask_val = BIT(0),
-};
diff --git a/drivers/genpd/renesas/r8a77980-sysc.c b/drivers/genpd/renesas/r8a77980-sysc.c
deleted file mode 100644 (file)
index 39ca84a..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas R-Car V3H System Controller
- *
- * Copyright (C) 2018 Renesas Electronics Corp.
- * Copyright (C) 2018 Cogent Embedded, Inc.
- */
-
-#include <linux/bits.h>
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a77980-sysc.h>
-
-#include "rcar-sysc.h"
-
-static const struct rcar_sysc_area r8a77980_areas[] __initconst = {
-       { "always-on",      0, 0, R8A77980_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca53-scu",   0x140, 0, R8A77980_PD_CA53_SCU, R8A77980_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca53-cpu0",  0x200, 0, R8A77980_PD_CA53_CPU0, R8A77980_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "ca53-cpu1",  0x200, 1, R8A77980_PD_CA53_CPU1, R8A77980_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "ca53-cpu2",  0x200, 2, R8A77980_PD_CA53_CPU2, R8A77980_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "ca53-cpu3",  0x200, 3, R8A77980_PD_CA53_CPU3, R8A77980_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "cr7",        0x240, 0, R8A77980_PD_CR7,      R8A77980_PD_ALWAYS_ON },
-       { "a3ir",       0x180, 0, R8A77980_PD_A3IR,     R8A77980_PD_ALWAYS_ON },
-       { "a2ir0",      0x400, 0, R8A77980_PD_A2IR0,    R8A77980_PD_A3IR },
-       { "a2ir1",      0x400, 1, R8A77980_PD_A2IR1,    R8A77980_PD_A3IR },
-       { "a2ir2",      0x400, 2, R8A77980_PD_A2IR2,    R8A77980_PD_A3IR },
-       { "a2ir3",      0x400, 3, R8A77980_PD_A2IR3,    R8A77980_PD_A3IR },
-       { "a2ir4",      0x400, 4, R8A77980_PD_A2IR4,    R8A77980_PD_A3IR },
-       { "a2ir5",      0x400, 5, R8A77980_PD_A2IR5,    R8A77980_PD_A3IR },
-       { "a2sc0",      0x400, 6, R8A77980_PD_A2SC0,    R8A77980_PD_A3IR },
-       { "a2sc1",      0x400, 7, R8A77980_PD_A2SC1,    R8A77980_PD_A3IR },
-       { "a2sc2",      0x400, 8, R8A77980_PD_A2SC2,    R8A77980_PD_A3IR },
-       { "a2sc3",      0x400, 9, R8A77980_PD_A2SC3,    R8A77980_PD_A3IR },
-       { "a2sc4",      0x400, 10, R8A77980_PD_A2SC4,   R8A77980_PD_A3IR },
-       { "a2dp0",      0x400, 11, R8A77980_PD_A2DP0,   R8A77980_PD_A3IR },
-       { "a2dp1",      0x400, 12, R8A77980_PD_A2DP1,   R8A77980_PD_A3IR },
-       { "a2cn",       0x400, 13, R8A77980_PD_A2CN,    R8A77980_PD_A3IR },
-       { "a3vip0",     0x2c0, 0, R8A77980_PD_A3VIP0,   R8A77980_PD_ALWAYS_ON },
-       { "a3vip1",     0x300, 0, R8A77980_PD_A3VIP1,   R8A77980_PD_ALWAYS_ON },
-       { "a3vip2",     0x280, 0, R8A77980_PD_A3VIP2,   R8A77980_PD_ALWAYS_ON },
-};
-
-const struct rcar_sysc_info r8a77980_sysc_info __initconst = {
-       .areas = r8a77980_areas,
-       .num_areas = ARRAY_SIZE(r8a77980_areas),
-       .extmask_offs = 0x138,
-       .extmask_val = BIT(0),
-};
diff --git a/drivers/genpd/renesas/r8a77990-sysc.c b/drivers/genpd/renesas/r8a77990-sysc.c
deleted file mode 100644 (file)
index 9f92737..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas R-Car E3 System Controller
- *
- * Copyright (C) 2018 Renesas Electronics Corp.
- */
-
-#include <linux/bits.h>
-#include <linux/kernel.h>
-#include <linux/sys_soc.h>
-
-#include <dt-bindings/power/r8a77990-sysc.h>
-
-#include "rcar-sysc.h"
-
-static struct rcar_sysc_area r8a77990_areas[] __initdata = {
-       { "always-on",      0, 0, R8A77990_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca53-scu",   0x140, 0, R8A77990_PD_CA53_SCU,  R8A77990_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca53-cpu0",  0x200, 0, R8A77990_PD_CA53_CPU0, R8A77990_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "ca53-cpu1",  0x200, 1, R8A77990_PD_CA53_CPU1, R8A77990_PD_CA53_SCU,
-         PD_CPU_NOCR },
-       { "cr7",        0x240, 0, R8A77990_PD_CR7,      R8A77990_PD_ALWAYS_ON },
-       { "a3vc",       0x380, 0, R8A77990_PD_A3VC,     R8A77990_PD_ALWAYS_ON },
-       { "a2vc1",      0x3c0, 1, R8A77990_PD_A2VC1,    R8A77990_PD_A3VC },
-       { "3dg-a",      0x100, 0, R8A77990_PD_3DG_A,    R8A77990_PD_ALWAYS_ON },
-       { "3dg-b",      0x100, 1, R8A77990_PD_3DG_B,    R8A77990_PD_3DG_A },
-};
-
-/* Fixups for R-Car E3 ES1.0 revision */
-static const struct soc_device_attribute r8a77990[] __initconst = {
-       { .soc_id = "r8a77990", .revision = "ES1.0" },
-       { /* sentinel */ }
-};
-
-static int __init r8a77990_sysc_init(void)
-{
-       if (soc_device_match(r8a77990)) {
-               /* Fix incorrect 3DG hierarchy */
-               swap(r8a77990_areas[7], r8a77990_areas[8]);
-               r8a77990_areas[7].parent = R8A77990_PD_ALWAYS_ON;
-               r8a77990_areas[8].parent = R8A77990_PD_3DG_B;
-       }
-
-       return 0;
-}
-
-const struct rcar_sysc_info r8a77990_sysc_info __initconst = {
-       .init = r8a77990_sysc_init,
-       .areas = r8a77990_areas,
-       .num_areas = ARRAY_SIZE(r8a77990_areas),
-       .extmask_offs = 0x2f8,
-       .extmask_val = BIT(0),
-};
diff --git a/drivers/genpd/renesas/r8a77995-sysc.c b/drivers/genpd/renesas/r8a77995-sysc.c
deleted file mode 100644 (file)
index efcc67e..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas R-Car D3 System Controller
- *
- * Copyright (C) 2017 Glider bvba
- */
-
-#include <linux/kernel.h>
-
-#include <dt-bindings/power/r8a77995-sysc.h>
-
-#include "rcar-sysc.h"
-
-static const struct rcar_sysc_area r8a77995_areas[] __initconst = {
-       { "always-on",     0, 0, R8A77995_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "ca53-scu",  0x140, 0, R8A77995_PD_CA53_SCU,  R8A77995_PD_ALWAYS_ON,
-         PD_SCU },
-       { "ca53-cpu0", 0x200, 0, R8A77995_PD_CA53_CPU0, R8A77995_PD_CA53_SCU,
-         PD_CPU_NOCR },
-};
-
-
-const struct rcar_sysc_info r8a77995_sysc_info __initconst = {
-       .areas = r8a77995_areas,
-       .num_areas = ARRAY_SIZE(r8a77995_areas),
-};
diff --git a/drivers/genpd/renesas/r8a779a0-sysc.c b/drivers/genpd/renesas/r8a779a0-sysc.c
deleted file mode 100644 (file)
index 04f1bc3..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas R-Car V3U System Controller
- *
- * Copyright (C) 2020 Renesas Electronics Corp.
- */
-
-#include <linux/bits.h>
-#include <linux/clk/renesas.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/of_address.h>
-#include <linux/pm_domain.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-
-#include <dt-bindings/power/r8a779a0-sysc.h>
-
-#include "rcar-gen4-sysc.h"
-
-static struct rcar_gen4_sysc_area r8a779a0_areas[] __initdata = {
-       { "always-on",  R8A779A0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "a3e0",       R8A779A0_PD_A3E0, R8A779A0_PD_ALWAYS_ON, PD_SCU },
-       { "a3e1",       R8A779A0_PD_A3E1, R8A779A0_PD_ALWAYS_ON, PD_SCU },
-       { "a2e0d0",     R8A779A0_PD_A2E0D0, R8A779A0_PD_A3E0, PD_SCU },
-       { "a2e0d1",     R8A779A0_PD_A2E0D1, R8A779A0_PD_A3E0, PD_SCU },
-       { "a2e1d0",     R8A779A0_PD_A2E1D0, R8A779A0_PD_A3E1, PD_SCU },
-       { "a2e1d1",     R8A779A0_PD_A2E1D1, R8A779A0_PD_A3E1, PD_SCU },
-       { "a1e0d0c0",   R8A779A0_PD_A1E0D0C0, R8A779A0_PD_A2E0D0, PD_CPU_NOCR },
-       { "a1e0d0c1",   R8A779A0_PD_A1E0D0C1, R8A779A0_PD_A2E0D0, PD_CPU_NOCR },
-       { "a1e0d1c0",   R8A779A0_PD_A1E0D1C0, R8A779A0_PD_A2E0D1, PD_CPU_NOCR },
-       { "a1e0d1c1",   R8A779A0_PD_A1E0D1C1, R8A779A0_PD_A2E0D1, PD_CPU_NOCR },
-       { "a1e1d0c0",   R8A779A0_PD_A1E1D0C0, R8A779A0_PD_A2E1D0, PD_CPU_NOCR },
-       { "a1e1d0c1",   R8A779A0_PD_A1E1D0C1, R8A779A0_PD_A2E1D0, PD_CPU_NOCR },
-       { "a1e1d1c0",   R8A779A0_PD_A1E1D1C0, R8A779A0_PD_A2E1D1, PD_CPU_NOCR },
-       { "a1e1d1c1",   R8A779A0_PD_A1E1D1C1, R8A779A0_PD_A2E1D1, PD_CPU_NOCR },
-       { "3dg-a",      R8A779A0_PD_3DG_A, R8A779A0_PD_ALWAYS_ON },
-       { "3dg-b",      R8A779A0_PD_3DG_B, R8A779A0_PD_3DG_A },
-       { "a3vip0",     R8A779A0_PD_A3VIP0, R8A779A0_PD_ALWAYS_ON },
-       { "a3vip1",     R8A779A0_PD_A3VIP1, R8A779A0_PD_ALWAYS_ON },
-       { "a3vip3",     R8A779A0_PD_A3VIP3, R8A779A0_PD_ALWAYS_ON },
-       { "a3vip2",     R8A779A0_PD_A3VIP2, R8A779A0_PD_ALWAYS_ON },
-       { "a3isp01",    R8A779A0_PD_A3ISP01, R8A779A0_PD_ALWAYS_ON },
-       { "a3isp23",    R8A779A0_PD_A3ISP23, R8A779A0_PD_ALWAYS_ON },
-       { "a3ir",       R8A779A0_PD_A3IR, R8A779A0_PD_ALWAYS_ON },
-       { "a2cn0",      R8A779A0_PD_A2CN0, R8A779A0_PD_A3IR },
-       { "a2imp01",    R8A779A0_PD_A2IMP01, R8A779A0_PD_A3IR },
-       { "a2dp0",      R8A779A0_PD_A2DP0, R8A779A0_PD_A3IR },
-       { "a2cv0",      R8A779A0_PD_A2CV0, R8A779A0_PD_A3IR },
-       { "a2cv1",      R8A779A0_PD_A2CV1, R8A779A0_PD_A3IR },
-       { "a2cv4",      R8A779A0_PD_A2CV4, R8A779A0_PD_A3IR },
-       { "a2cv6",      R8A779A0_PD_A2CV6, R8A779A0_PD_A3IR },
-       { "a2cn2",      R8A779A0_PD_A2CN2, R8A779A0_PD_A3IR },
-       { "a2imp23",    R8A779A0_PD_A2IMP23, R8A779A0_PD_A3IR },
-       { "a2dp1",      R8A779A0_PD_A2DP1, R8A779A0_PD_A3IR },
-       { "a2cv2",      R8A779A0_PD_A2CV2, R8A779A0_PD_A3IR },
-       { "a2cv3",      R8A779A0_PD_A2CV3, R8A779A0_PD_A3IR },
-       { "a2cv5",      R8A779A0_PD_A2CV5, R8A779A0_PD_A3IR },
-       { "a2cv7",      R8A779A0_PD_A2CV7, R8A779A0_PD_A3IR },
-       { "a2cn1",      R8A779A0_PD_A2CN1, R8A779A0_PD_A3IR },
-       { "a1cnn0",     R8A779A0_PD_A1CNN0, R8A779A0_PD_A2CN0 },
-       { "a1cnn2",     R8A779A0_PD_A1CNN2, R8A779A0_PD_A2CN2 },
-       { "a1dsp0",     R8A779A0_PD_A1DSP0, R8A779A0_PD_A2CN2 },
-       { "a1cnn1",     R8A779A0_PD_A1CNN1, R8A779A0_PD_A2CN1 },
-       { "a1dsp1",     R8A779A0_PD_A1DSP1, R8A779A0_PD_A2CN1 },
-};
-
-const struct rcar_gen4_sysc_info r8a779a0_sysc_info __initconst = {
-       .areas = r8a779a0_areas,
-       .num_areas = ARRAY_SIZE(r8a779a0_areas),
-};
diff --git a/drivers/genpd/renesas/r8a779f0-sysc.c b/drivers/genpd/renesas/r8a779f0-sysc.c
deleted file mode 100644 (file)
index 5602aa6..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas R-Car S4-8 System Controller
- *
- * Copyright (C) 2021 Renesas Electronics Corp.
- */
-
-#include <linux/bits.h>
-#include <linux/clk/renesas.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/of_address.h>
-#include <linux/pm_domain.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-
-#include <dt-bindings/power/r8a779f0-sysc.h>
-
-#include "rcar-gen4-sysc.h"
-
-static struct rcar_gen4_sysc_area r8a779f0_areas[] __initdata = {
-       { "always-on",  R8A779F0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "a3e0",       R8A779F0_PD_A3E0, R8A779F0_PD_ALWAYS_ON, PD_SCU },
-       { "a3e1",       R8A779F0_PD_A3E1, R8A779F0_PD_ALWAYS_ON, PD_SCU },
-       { "a2e0d0",     R8A779F0_PD_A2E0D0, R8A779F0_PD_A3E0, PD_SCU },
-       { "a2e0d1",     R8A779F0_PD_A2E0D1, R8A779F0_PD_A3E0, PD_SCU },
-       { "a2e1d0",     R8A779F0_PD_A2E1D0, R8A779F0_PD_A3E1, PD_SCU },
-       { "a2e1d1",     R8A779F0_PD_A2E1D1, R8A779F0_PD_A3E1, PD_SCU },
-       { "a1e0d0c0",   R8A779F0_PD_A1E0D0C0, R8A779F0_PD_A2E0D0, PD_CPU_NOCR },
-       { "a1e0d0c1",   R8A779F0_PD_A1E0D0C1, R8A779F0_PD_A2E0D0, PD_CPU_NOCR },
-       { "a1e0d1c0",   R8A779F0_PD_A1E0D1C0, R8A779F0_PD_A2E0D1, PD_CPU_NOCR },
-       { "a1e0d1c1",   R8A779F0_PD_A1E0D1C1, R8A779F0_PD_A2E0D1, PD_CPU_NOCR },
-       { "a1e1d0c0",   R8A779F0_PD_A1E1D0C0, R8A779F0_PD_A2E1D0, PD_CPU_NOCR },
-       { "a1e1d0c1",   R8A779F0_PD_A1E1D0C1, R8A779F0_PD_A2E1D0, PD_CPU_NOCR },
-       { "a1e1d1c0",   R8A779F0_PD_A1E1D1C0, R8A779F0_PD_A2E1D1, PD_CPU_NOCR },
-       { "a1e1d1c1",   R8A779F0_PD_A1E1D1C1, R8A779F0_PD_A2E1D1, PD_CPU_NOCR },
-};
-
-const struct rcar_gen4_sysc_info r8a779f0_sysc_info __initconst = {
-       .areas = r8a779f0_areas,
-       .num_areas = ARRAY_SIZE(r8a779f0_areas),
-};
diff --git a/drivers/genpd/renesas/r8a779g0-sysc.c b/drivers/genpd/renesas/r8a779g0-sysc.c
deleted file mode 100644 (file)
index b932eba..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Renesas R-Car V4H System Controller
- *
- * Copyright (C) 2022 Renesas Electronics Corp.
- */
-
-#include <linux/bits.h>
-#include <linux/clk/renesas.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/of_address.h>
-#include <linux/pm_domain.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-
-#include <dt-bindings/power/r8a779g0-sysc.h>
-
-#include "rcar-gen4-sysc.h"
-
-static struct rcar_gen4_sysc_area r8a779g0_areas[] __initdata = {
-       { "always-on",  R8A779G0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
-       { "a3e0",       R8A779G0_PD_A3E0, R8A779G0_PD_ALWAYS_ON, PD_SCU },
-       { "a2e0d0",     R8A779G0_PD_A2E0D0, R8A779G0_PD_A3E0, PD_SCU },
-       { "a2e0d1",     R8A779G0_PD_A2E0D1, R8A779G0_PD_A3E0, PD_SCU },
-       { "a1e0d0c0",   R8A779G0_PD_A1E0D0C0, R8A779G0_PD_A2E0D0, PD_CPU_NOCR },
-       { "a1e0d0c1",   R8A779G0_PD_A1E0D0C1, R8A779G0_PD_A2E0D0, PD_CPU_NOCR },
-       { "a1e0d1c0",   R8A779G0_PD_A1E0D1C0, R8A779G0_PD_A2E0D1, PD_CPU_NOCR },
-       { "a1e0d1c1",   R8A779G0_PD_A1E0D1C1, R8A779G0_PD_A2E0D1, PD_CPU_NOCR },
-       { "a33dga",     R8A779G0_PD_A33DGA, R8A779G0_PD_ALWAYS_ON },
-       { "a23dgb",     R8A779G0_PD_A23DGB, R8A779G0_PD_A33DGA },
-       { "a3vip0",     R8A779G0_PD_A3VIP0, R8A779G0_PD_ALWAYS_ON },
-       { "a3vip1",     R8A779G0_PD_A3VIP1, R8A779G0_PD_ALWAYS_ON },
-       { "a3vip2",     R8A779G0_PD_A3VIP2, R8A779G0_PD_ALWAYS_ON },
-       { "a3dul",      R8A779G0_PD_A3DUL, R8A779G0_PD_ALWAYS_ON },
-       { "a3isp0",     R8A779G0_PD_A3ISP0, R8A779G0_PD_ALWAYS_ON },
-       { "a3isp1",     R8A779G0_PD_A3ISP1, R8A779G0_PD_ALWAYS_ON },
-       { "a3ir",       R8A779G0_PD_A3IR, R8A779G0_PD_ALWAYS_ON },
-       { "a2cn0",      R8A779G0_PD_A2CN0, R8A779G0_PD_A3IR },
-       { "a1cnn0",     R8A779G0_PD_A1CNN0, R8A779G0_PD_A2CN0 },
-       { "a1dsp0",     R8A779G0_PD_A1DSP0, R8A779G0_PD_A2CN0 },
-       { "a1dsp1",     R8A779G0_PD_A1DSP1, R8A779G0_PD_A2CN0 },
-       { "a1dsp2",     R8A779G0_PD_A1DSP2, R8A779G0_PD_A2CN0 },
-       { "a1dsp3",     R8A779G0_PD_A1DSP3, R8A779G0_PD_A2CN0 },
-       { "a2imp01",    R8A779G0_PD_A2IMP01, R8A779G0_PD_A3IR },
-       { "a2imp23",    R8A779G0_PD_A2IMP23, R8A779G0_PD_A3IR },
-       { "a2psc",      R8A779G0_PD_A2PSC, R8A779G0_PD_A3IR },
-       { "a2dma",      R8A779G0_PD_A2DMA, R8A779G0_PD_A3IR },
-       { "a2cv0",      R8A779G0_PD_A2CV0, R8A779G0_PD_A3IR },
-       { "a2cv1",      R8A779G0_PD_A2CV1, R8A779G0_PD_A3IR },
-       { "a2cv2",      R8A779G0_PD_A2CV2, R8A779G0_PD_A3IR },
-       { "a2cv3",      R8A779G0_PD_A2CV3, R8A779G0_PD_A3IR },
-};
-
-const struct rcar_gen4_sysc_info r8a779g0_sysc_info __initconst = {
-       .areas = r8a779g0_areas,
-       .num_areas = ARRAY_SIZE(r8a779g0_areas),
-};
diff --git a/drivers/genpd/renesas/rcar-gen4-sysc.c b/drivers/genpd/renesas/rcar-gen4-sysc.c
deleted file mode 100644 (file)
index 9e5e6e0..0000000
+++ /dev/null
@@ -1,379 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * R-Car Gen4 SYSC Power management support
- *
- * Copyright (C) 2021 Renesas Electronics Corp.
- */
-
-#include <linux/bits.h>
-#include <linux/clk/renesas.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/of_address.h>
-#include <linux/pm_domain.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-
-#include "rcar-gen4-sysc.h"
-
-/* SYSC Common */
-#define SYSCSR         0x000   /* SYSC Status Register */
-#define SYSCPONSR(x)   (0x800 + ((x) * 0x4)) /* Power-ON Status Register 0 */
-#define SYSCPOFFSR(x)  (0x808 + ((x) * 0x4)) /* Power-OFF Status Register */
-#define SYSCISCR(x)    (0x810 + ((x) * 0x4)) /* Interrupt Status/Clear Register */
-#define SYSCIER(x)     (0x820 + ((x) * 0x4)) /* Interrupt Enable Register */
-#define SYSCIMR(x)     (0x830 + ((x) * 0x4)) /* Interrupt Mask Register */
-
-/* Power Domain Registers */
-#define PDRSR(n)       (0x1000 + ((n) * 0x40))
-#define PDRONCR(n)     (0x1004 + ((n) * 0x40))
-#define PDROFFCR(n)    (0x1008 + ((n) * 0x40))
-#define PDRESR(n)      (0x100C + ((n) * 0x40))
-
-/* PWRON/PWROFF */
-#define PWRON_PWROFF           BIT(0)  /* Power-ON/OFF request */
-
-/* PDRESR */
-#define PDRESR_ERR             BIT(0)
-
-/* PDRSR */
-#define PDRSR_OFF              BIT(0)  /* Power-OFF state */
-#define PDRSR_ON               BIT(4)  /* Power-ON state */
-#define PDRSR_OFF_STATE                BIT(8)  /* Processing Power-OFF sequence */
-#define PDRSR_ON_STATE         BIT(12) /* Processing Power-ON sequence */
-
-#define SYSCSR_BUSY            GENMASK(1, 0)   /* All bit sets is not busy */
-
-#define SYSCSR_TIMEOUT         10000
-#define SYSCSR_DELAY_US                10
-
-#define PDRESR_RETRIES         1000
-#define PDRESR_DELAY_US                10
-
-#define SYSCISR_TIMEOUT                10000
-#define SYSCISR_DELAY_US       10
-
-#define RCAR_GEN4_PD_ALWAYS_ON 64
-#define NUM_DOMAINS_EACH_REG   BITS_PER_TYPE(u32)
-
-static void __iomem *rcar_gen4_sysc_base;
-static DEFINE_SPINLOCK(rcar_gen4_sysc_lock); /* SMP CPUs + I/O devices */
-
-static int rcar_gen4_sysc_pwr_on_off(u8 pdr, bool on)
-{
-       unsigned int reg_offs;
-       u32 val;
-       int ret;
-
-       if (on)
-               reg_offs = PDRONCR(pdr);
-       else
-               reg_offs = PDROFFCR(pdr);
-
-       /* Wait until SYSC is ready to accept a power request */
-       ret = readl_poll_timeout_atomic(rcar_gen4_sysc_base + SYSCSR, val,
-                                       (val & SYSCSR_BUSY) == SYSCSR_BUSY,
-                                       SYSCSR_DELAY_US, SYSCSR_TIMEOUT);
-       if (ret < 0)
-               return -EAGAIN;
-
-       /* Submit power shutoff or power resume request */
-       iowrite32(PWRON_PWROFF, rcar_gen4_sysc_base + reg_offs);
-
-       return 0;
-}
-
-static int clear_irq_flags(unsigned int reg_idx, unsigned int isr_mask)
-{
-       u32 val;
-       int ret;
-
-       iowrite32(isr_mask, rcar_gen4_sysc_base + SYSCISCR(reg_idx));
-
-       ret = readl_poll_timeout_atomic(rcar_gen4_sysc_base + SYSCISCR(reg_idx),
-                                       val, !(val & isr_mask),
-                                       SYSCISR_DELAY_US, SYSCISR_TIMEOUT);
-       if (ret < 0) {
-               pr_err("\n %s : Can not clear IRQ flags in SYSCISCR", __func__);
-               return -EIO;
-       }
-
-       return 0;
-}
-
-static int rcar_gen4_sysc_power(u8 pdr, bool on)
-{
-       unsigned int isr_mask;
-       unsigned int reg_idx, bit_idx;
-       unsigned int status;
-       unsigned long flags;
-       int ret = 0;
-       u32 val;
-       int k;
-
-       spin_lock_irqsave(&rcar_gen4_sysc_lock, flags);
-
-       reg_idx = pdr / NUM_DOMAINS_EACH_REG;
-       bit_idx = pdr % NUM_DOMAINS_EACH_REG;
-
-       isr_mask = BIT(bit_idx);
-
-       /*
-        * The interrupt source needs to be enabled, but masked, to prevent the
-        * CPU from receiving it.
-        */
-       iowrite32(ioread32(rcar_gen4_sysc_base + SYSCIER(reg_idx)) | isr_mask,
-                 rcar_gen4_sysc_base + SYSCIER(reg_idx));
-       iowrite32(ioread32(rcar_gen4_sysc_base + SYSCIMR(reg_idx)) | isr_mask,
-                 rcar_gen4_sysc_base + SYSCIMR(reg_idx));
-
-       ret = clear_irq_flags(reg_idx, isr_mask);
-       if (ret)
-               goto out;
-
-       /* Submit power shutoff or resume request until it was accepted */
-       for (k = 0; k < PDRESR_RETRIES; k++) {
-               ret = rcar_gen4_sysc_pwr_on_off(pdr, on);
-               if (ret)
-                       goto out;
-
-               status = ioread32(rcar_gen4_sysc_base + PDRESR(pdr));
-               if (!(status & PDRESR_ERR))
-                       break;
-
-               udelay(PDRESR_DELAY_US);
-       }
-
-       if (k == PDRESR_RETRIES) {
-               ret = -EIO;
-               goto out;
-       }
-
-       /* Wait until the power shutoff or resume request has completed * */
-       ret = readl_poll_timeout_atomic(rcar_gen4_sysc_base + SYSCISCR(reg_idx),
-                                       val, (val & isr_mask),
-                                       SYSCISR_DELAY_US, SYSCISR_TIMEOUT);
-       if (ret < 0) {
-               ret = -EIO;
-               goto out;
-       }
-
-       /* Clear interrupt flags */
-       ret = clear_irq_flags(reg_idx, isr_mask);
-       if (ret)
-               goto out;
-
- out:
-       spin_unlock_irqrestore(&rcar_gen4_sysc_lock, flags);
-
-       pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off",
-                pdr, ioread32(rcar_gen4_sysc_base + SYSCISCR(reg_idx)), ret);
-       return ret;
-}
-
-static bool rcar_gen4_sysc_power_is_off(u8 pdr)
-{
-       unsigned int st;
-
-       st = ioread32(rcar_gen4_sysc_base + PDRSR(pdr));
-
-       if (st & PDRSR_OFF)
-               return true;
-
-       return false;
-}
-
-struct rcar_gen4_sysc_pd {
-       struct generic_pm_domain genpd;
-       u8 pdr;
-       unsigned int flags;
-       char name[];
-};
-
-static inline struct rcar_gen4_sysc_pd *to_rcar_gen4_pd(struct generic_pm_domain *d)
-{
-       return container_of(d, struct rcar_gen4_sysc_pd, genpd);
-}
-
-static int rcar_gen4_sysc_pd_power_off(struct generic_pm_domain *genpd)
-{
-       struct rcar_gen4_sysc_pd *pd = to_rcar_gen4_pd(genpd);
-
-       pr_debug("%s: %s\n", __func__, genpd->name);
-       return rcar_gen4_sysc_power(pd->pdr, false);
-}
-
-static int rcar_gen4_sysc_pd_power_on(struct generic_pm_domain *genpd)
-{
-       struct rcar_gen4_sysc_pd *pd = to_rcar_gen4_pd(genpd);
-
-       pr_debug("%s: %s\n", __func__, genpd->name);
-       return rcar_gen4_sysc_power(pd->pdr, true);
-}
-
-static int __init rcar_gen4_sysc_pd_setup(struct rcar_gen4_sysc_pd *pd)
-{
-       struct generic_pm_domain *genpd = &pd->genpd;
-       const char *name = pd->genpd.name;
-       int error;
-
-       if (pd->flags & PD_CPU) {
-               /*
-                * This domain contains a CPU core and therefore it should
-                * only be turned off if the CPU is not in use.
-                */
-               pr_debug("PM domain %s contains %s\n", name, "CPU");
-               genpd->flags |= GENPD_FLAG_ALWAYS_ON;
-       } else if (pd->flags & PD_SCU) {
-               /*
-                * This domain contains an SCU and cache-controller, and
-                * therefore it should only be turned off if the CPU cores are
-                * not in use.
-                */
-               pr_debug("PM domain %s contains %s\n", name, "SCU");
-               genpd->flags |= GENPD_FLAG_ALWAYS_ON;
-       } else if (pd->flags & PD_NO_CR) {
-               /*
-                * This domain cannot be turned off.
-                */
-               genpd->flags |= GENPD_FLAG_ALWAYS_ON;
-       }
-
-       if (!(pd->flags & (PD_CPU | PD_SCU))) {
-               /* Enable Clock Domain for I/O devices */
-               genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
-               genpd->attach_dev = cpg_mssr_attach_dev;
-               genpd->detach_dev = cpg_mssr_detach_dev;
-       }
-
-       genpd->power_off = rcar_gen4_sysc_pd_power_off;
-       genpd->power_on = rcar_gen4_sysc_pd_power_on;
-
-       if (pd->flags & (PD_CPU | PD_NO_CR)) {
-               /* Skip CPUs (handled by SMP code) and areas without control */
-               pr_debug("%s: Not touching %s\n", __func__, genpd->name);
-               goto finalize;
-       }
-
-       if (!rcar_gen4_sysc_power_is_off(pd->pdr)) {
-               pr_debug("%s: %s is already powered\n", __func__, genpd->name);
-               goto finalize;
-       }
-
-       rcar_gen4_sysc_power(pd->pdr, true);
-
-finalize:
-       error = pm_genpd_init(genpd, &simple_qos_governor, false);
-       if (error)
-               pr_err("Failed to init PM domain %s: %d\n", name, error);
-
-       return error;
-}
-
-static const struct of_device_id rcar_gen4_sysc_matches[] __initconst = {
-#ifdef CONFIG_SYSC_R8A779A0
-       { .compatible = "renesas,r8a779a0-sysc", .data = &r8a779a0_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A779F0
-       { .compatible = "renesas,r8a779f0-sysc", .data = &r8a779f0_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A779G0
-       { .compatible = "renesas,r8a779g0-sysc", .data = &r8a779g0_sysc_info },
-#endif
-       { /* sentinel */ }
-};
-
-struct rcar_gen4_pm_domains {
-       struct genpd_onecell_data onecell_data;
-       struct generic_pm_domain *domains[RCAR_GEN4_PD_ALWAYS_ON + 1];
-};
-
-static struct genpd_onecell_data *rcar_gen4_sysc_onecell_data;
-
-static int __init rcar_gen4_sysc_pd_init(void)
-{
-       const struct rcar_gen4_sysc_info *info;
-       const struct of_device_id *match;
-       struct rcar_gen4_pm_domains *domains;
-       struct device_node *np;
-       void __iomem *base;
-       unsigned int i;
-       int error;
-
-       np = of_find_matching_node_and_match(NULL, rcar_gen4_sysc_matches, &match);
-       if (!np)
-               return -ENODEV;
-
-       info = match->data;
-
-       base = of_iomap(np, 0);
-       if (!base) {
-               pr_warn("%pOF: Cannot map regs\n", np);
-               error = -ENOMEM;
-               goto out_put;
-       }
-
-       rcar_gen4_sysc_base = base;
-
-       domains = kzalloc(sizeof(*domains), GFP_KERNEL);
-       if (!domains) {
-               error = -ENOMEM;
-               goto out_put;
-       }
-
-       domains->onecell_data.domains = domains->domains;
-       domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains);
-       rcar_gen4_sysc_onecell_data = &domains->onecell_data;
-
-       for (i = 0; i < info->num_areas; i++) {
-               const struct rcar_gen4_sysc_area *area = &info->areas[i];
-               struct rcar_gen4_sysc_pd *pd;
-               size_t n;
-
-               if (!area->name) {
-                       /* Skip NULLified area */
-                       continue;
-               }
-
-               n = strlen(area->name) + 1;
-               pd = kzalloc(sizeof(*pd) + n, GFP_KERNEL);
-               if (!pd) {
-                       error = -ENOMEM;
-                       goto out_put;
-               }
-
-               memcpy(pd->name, area->name, n);
-               pd->genpd.name = pd->name;
-               pd->pdr = area->pdr;
-               pd->flags = area->flags;
-
-               error = rcar_gen4_sysc_pd_setup(pd);
-               if (error)
-                       goto out_put;
-
-               domains->domains[area->pdr] = &pd->genpd;
-
-               if (area->parent < 0)
-                       continue;
-
-               error = pm_genpd_add_subdomain(domains->domains[area->parent],
-                                              &pd->genpd);
-               if (error) {
-                       pr_warn("Failed to add PM subdomain %s to parent %u\n",
-                               area->name, area->parent);
-                       goto out_put;
-               }
-       }
-
-       error = of_genpd_add_provider_onecell(np, &domains->onecell_data);
-
-out_put:
-       of_node_put(np);
-       return error;
-}
-early_initcall(rcar_gen4_sysc_pd_init);
diff --git a/drivers/genpd/renesas/rcar-gen4-sysc.h b/drivers/genpd/renesas/rcar-gen4-sysc.h
deleted file mode 100644 (file)
index 388cfa8..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * R-Car Gen4 System Controller
- *
- * Copyright (C) 2021 Renesas Electronics Corp.
- */
-#ifndef __SOC_RENESAS_RCAR_GEN4_SYSC_H__
-#define __SOC_RENESAS_RCAR_GEN4_SYSC_H__
-
-#include <linux/types.h>
-
-/*
- * Power Domain flags
- */
-#define PD_CPU         BIT(0)  /* Area contains main CPU core */
-#define PD_SCU         BIT(1)  /* Area contains SCU and L2 cache */
-#define PD_NO_CR       BIT(2)  /* Area lacks PWR{ON,OFF}CR registers */
-
-#define PD_CPU_NOCR    (PD_CPU | PD_NO_CR) /* CPU area lacks CR */
-#define PD_ALWAYS_ON   PD_NO_CR          /* Always-on area */
-
-/*
- * Description of a Power Area
- */
-struct rcar_gen4_sysc_area {
-       const char *name;
-       u8 pdr;                 /* PDRn */
-       s8 parent;              /* -1 if none */
-       u8 flags;               /* See PD_* */
-};
-
-/*
- * SoC-specific Power Area Description
- */
-struct rcar_gen4_sysc_info {
-       const struct rcar_gen4_sysc_area *areas;
-       unsigned int num_areas;
-};
-
-extern const struct rcar_gen4_sysc_info r8a779a0_sysc_info;
-extern const struct rcar_gen4_sysc_info r8a779f0_sysc_info;
-extern const struct rcar_gen4_sysc_info r8a779g0_sysc_info;
-
-#endif /* __SOC_RENESAS_RCAR_GEN4_SYSC_H__ */
diff --git a/drivers/genpd/renesas/rcar-sysc.c b/drivers/genpd/renesas/rcar-sysc.c
deleted file mode 100644 (file)
index eed4769..0000000
+++ /dev/null
@@ -1,494 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * R-Car SYSC Power management support
- *
- * Copyright (C) 2014  Magnus Damm
- * Copyright (C) 2015-2017 Glider bvba
- */
-
-#include <linux/clk/renesas.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/mm.h>
-#include <linux/of_address.h>
-#include <linux/pm_domain.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/soc/renesas/rcar-sysc.h>
-
-#include "rcar-sysc.h"
-
-/* SYSC Common */
-#define SYSCSR                 0x00    /* SYSC Status Register */
-#define SYSCISR                        0x04    /* Interrupt Status Register */
-#define SYSCISCR               0x08    /* Interrupt Status Clear Register */
-#define SYSCIER                        0x0c    /* Interrupt Enable Register */
-#define SYSCIMR                        0x10    /* Interrupt Mask Register */
-
-/* SYSC Status Register */
-#define SYSCSR_PONENB          1       /* Ready for power resume requests */
-#define SYSCSR_POFFENB         0       /* Ready for power shutoff requests */
-
-/*
- * Power Control Register Offsets inside the register block for each domain
- * Note: The "CR" registers for ARM cores exist on H1 only
- *      Use WFI to power off, CPG/APMU to resume ARM cores on R-Car Gen2
- *      Use PSCI on R-Car Gen3
- */
-#define PWRSR_OFFS             0x00    /* Power Status Register */
-#define PWROFFCR_OFFS          0x04    /* Power Shutoff Control Register */
-#define PWROFFSR_OFFS          0x08    /* Power Shutoff Status Register */
-#define PWRONCR_OFFS           0x0c    /* Power Resume Control Register */
-#define PWRONSR_OFFS           0x10    /* Power Resume Status Register */
-#define PWRER_OFFS             0x14    /* Power Shutoff/Resume Error */
-
-
-#define SYSCSR_TIMEOUT         100
-#define SYSCSR_DELAY_US                1
-
-#define PWRER_RETRIES          100
-#define PWRER_DELAY_US         1
-
-#define SYSCISR_TIMEOUT                1000
-#define SYSCISR_DELAY_US       1
-
-#define RCAR_PD_ALWAYS_ON      32      /* Always-on power area */
-
-struct rcar_sysc_ch {
-       u16 chan_offs;
-       u8 chan_bit;
-       u8 isr_bit;
-};
-
-static void __iomem *rcar_sysc_base;
-static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */
-static u32 rcar_sysc_extmask_offs, rcar_sysc_extmask_val;
-
-static int rcar_sysc_pwr_on_off(const struct rcar_sysc_ch *sysc_ch, bool on)
-{
-       unsigned int sr_bit, reg_offs;
-       u32 val;
-       int ret;
-
-       if (on) {
-               sr_bit = SYSCSR_PONENB;
-               reg_offs = PWRONCR_OFFS;
-       } else {
-               sr_bit = SYSCSR_POFFENB;
-               reg_offs = PWROFFCR_OFFS;
-       }
-
-       /* Wait until SYSC is ready to accept a power request */
-       ret = readl_poll_timeout_atomic(rcar_sysc_base + SYSCSR, val,
-                                       val & BIT(sr_bit), SYSCSR_DELAY_US,
-                                       SYSCSR_TIMEOUT);
-       if (ret)
-               return -EAGAIN;
-
-       /* Submit power shutoff or power resume request */
-       iowrite32(BIT(sysc_ch->chan_bit),
-                 rcar_sysc_base + sysc_ch->chan_offs + reg_offs);
-
-       return 0;
-}
-
-static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on)
-{
-       unsigned int isr_mask = BIT(sysc_ch->isr_bit);
-       unsigned int chan_mask = BIT(sysc_ch->chan_bit);
-       unsigned int status, k;
-       unsigned long flags;
-       int ret;
-
-       spin_lock_irqsave(&rcar_sysc_lock, flags);
-
-       /*
-        * Mask external power requests for CPU or 3DG domains
-        */
-       if (rcar_sysc_extmask_val) {
-               iowrite32(rcar_sysc_extmask_val,
-                         rcar_sysc_base + rcar_sysc_extmask_offs);
-       }
-
-       /*
-        * The interrupt source needs to be enabled, but masked, to prevent the
-        * CPU from receiving it.
-        */
-       iowrite32(ioread32(rcar_sysc_base + SYSCIMR) | isr_mask,
-                 rcar_sysc_base + SYSCIMR);
-       iowrite32(ioread32(rcar_sysc_base + SYSCIER) | isr_mask,
-                 rcar_sysc_base + SYSCIER);
-
-       iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
-
-       /* Submit power shutoff or resume request until it was accepted */
-       for (k = 0; k < PWRER_RETRIES; k++) {
-               ret = rcar_sysc_pwr_on_off(sysc_ch, on);
-               if (ret)
-                       goto out;
-
-               status = ioread32(rcar_sysc_base +
-                                 sysc_ch->chan_offs + PWRER_OFFS);
-               if (!(status & chan_mask))
-                       break;
-
-               udelay(PWRER_DELAY_US);
-       }
-
-       if (k == PWRER_RETRIES) {
-               ret = -EIO;
-               goto out;
-       }
-
-       /* Wait until the power shutoff or resume request has completed * */
-       ret = readl_poll_timeout_atomic(rcar_sysc_base + SYSCISR, status,
-                                       status & isr_mask, SYSCISR_DELAY_US,
-                                       SYSCISR_TIMEOUT);
-       if (ret)
-               ret = -EIO;
-
-       iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
-
- out:
-       if (rcar_sysc_extmask_val)
-               iowrite32(0, rcar_sysc_base + rcar_sysc_extmask_offs);
-
-       spin_unlock_irqrestore(&rcar_sysc_lock, flags);
-
-       pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off",
-                sysc_ch->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret);
-       return ret;
-}
-
-static bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch)
-{
-       unsigned int st;
-
-       st = ioread32(rcar_sysc_base + sysc_ch->chan_offs + PWRSR_OFFS);
-       if (st & BIT(sysc_ch->chan_bit))
-               return true;
-
-       return false;
-}
-
-struct rcar_sysc_pd {
-       struct generic_pm_domain genpd;
-       struct rcar_sysc_ch ch;
-       unsigned int flags;
-       char name[];
-};
-
-static inline struct rcar_sysc_pd *to_rcar_pd(struct generic_pm_domain *d)
-{
-       return container_of(d, struct rcar_sysc_pd, genpd);
-}
-
-static int rcar_sysc_pd_power_off(struct generic_pm_domain *genpd)
-{
-       struct rcar_sysc_pd *pd = to_rcar_pd(genpd);
-
-       pr_debug("%s: %s\n", __func__, genpd->name);
-       return rcar_sysc_power(&pd->ch, false);
-}
-
-static int rcar_sysc_pd_power_on(struct generic_pm_domain *genpd)
-{
-       struct rcar_sysc_pd *pd = to_rcar_pd(genpd);
-
-       pr_debug("%s: %s\n", __func__, genpd->name);
-       return rcar_sysc_power(&pd->ch, true);
-}
-
-static bool has_cpg_mstp;
-
-static int __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd)
-{
-       struct generic_pm_domain *genpd = &pd->genpd;
-       const char *name = pd->genpd.name;
-       int error;
-
-       if (pd->flags & PD_CPU) {
-               /*
-                * This domain contains a CPU core and therefore it should
-                * only be turned off if the CPU is not in use.
-                */
-               pr_debug("PM domain %s contains %s\n", name, "CPU");
-               genpd->flags |= GENPD_FLAG_ALWAYS_ON;
-       } else if (pd->flags & PD_SCU) {
-               /*
-                * This domain contains an SCU and cache-controller, and
-                * therefore it should only be turned off if the CPU cores are
-                * not in use.
-                */
-               pr_debug("PM domain %s contains %s\n", name, "SCU");
-               genpd->flags |= GENPD_FLAG_ALWAYS_ON;
-       } else if (pd->flags & PD_NO_CR) {
-               /*
-                * This domain cannot be turned off.
-                */
-               genpd->flags |= GENPD_FLAG_ALWAYS_ON;
-       }
-
-       if (!(pd->flags & (PD_CPU | PD_SCU))) {
-               /* Enable Clock Domain for I/O devices */
-               genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
-               if (has_cpg_mstp) {
-                       genpd->attach_dev = cpg_mstp_attach_dev;
-                       genpd->detach_dev = cpg_mstp_detach_dev;
-               } else {
-                       genpd->attach_dev = cpg_mssr_attach_dev;
-                       genpd->detach_dev = cpg_mssr_detach_dev;
-               }
-       }
-
-       genpd->power_off = rcar_sysc_pd_power_off;
-       genpd->power_on = rcar_sysc_pd_power_on;
-
-       if (pd->flags & (PD_CPU | PD_NO_CR)) {
-               /* Skip CPUs (handled by SMP code) and areas without control */
-               pr_debug("%s: Not touching %s\n", __func__, genpd->name);
-               goto finalize;
-       }
-
-       if (!rcar_sysc_power_is_off(&pd->ch)) {
-               pr_debug("%s: %s is already powered\n", __func__, genpd->name);
-               goto finalize;
-       }
-
-       rcar_sysc_power(&pd->ch, true);
-
-finalize:
-       error = pm_genpd_init(genpd, &simple_qos_governor, false);
-       if (error)
-               pr_err("Failed to init PM domain %s: %d\n", name, error);
-
-       return error;
-}
-
-static const struct of_device_id rcar_sysc_matches[] __initconst = {
-#ifdef CONFIG_SYSC_R8A7742
-       { .compatible = "renesas,r8a7742-sysc", .data = &r8a7742_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A7743
-       { .compatible = "renesas,r8a7743-sysc", .data = &r8a7743_sysc_info },
-       /* RZ/G1N is identical to RZ/G2M w.r.t. power domains. */
-       { .compatible = "renesas,r8a7744-sysc", .data = &r8a7743_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A7745
-       { .compatible = "renesas,r8a7745-sysc", .data = &r8a7745_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A77470
-       { .compatible = "renesas,r8a77470-sysc", .data = &r8a77470_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A774A1
-       { .compatible = "renesas,r8a774a1-sysc", .data = &r8a774a1_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A774B1
-       { .compatible = "renesas,r8a774b1-sysc", .data = &r8a774b1_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A774C0
-       { .compatible = "renesas,r8a774c0-sysc", .data = &r8a774c0_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A774E1
-       { .compatible = "renesas,r8a774e1-sysc", .data = &r8a774e1_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A7779
-       { .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A7790
-       { .compatible = "renesas,r8a7790-sysc", .data = &r8a7790_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A7791
-       { .compatible = "renesas,r8a7791-sysc", .data = &r8a7791_sysc_info },
-       /* R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. */
-       { .compatible = "renesas,r8a7793-sysc", .data = &r8a7791_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A7792
-       { .compatible = "renesas,r8a7792-sysc", .data = &r8a7792_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A7794
-       { .compatible = "renesas,r8a7794-sysc", .data = &r8a7794_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A7795
-       { .compatible = "renesas,r8a7795-sysc", .data = &r8a7795_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A77960
-       { .compatible = "renesas,r8a7796-sysc", .data = &r8a77960_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A77961
-       { .compatible = "renesas,r8a77961-sysc", .data = &r8a77961_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A77965
-       { .compatible = "renesas,r8a77965-sysc", .data = &r8a77965_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A77970
-       { .compatible = "renesas,r8a77970-sysc", .data = &r8a77970_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A77980
-       { .compatible = "renesas,r8a77980-sysc", .data = &r8a77980_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A77990
-       { .compatible = "renesas,r8a77990-sysc", .data = &r8a77990_sysc_info },
-#endif
-#ifdef CONFIG_SYSC_R8A77995
-       { .compatible = "renesas,r8a77995-sysc", .data = &r8a77995_sysc_info },
-#endif
-       { /* sentinel */ }
-};
-
-struct rcar_pm_domains {
-       struct genpd_onecell_data onecell_data;
-       struct generic_pm_domain *domains[RCAR_PD_ALWAYS_ON + 1];
-};
-
-static struct genpd_onecell_data *rcar_sysc_onecell_data;
-
-static int __init rcar_sysc_pd_init(void)
-{
-       const struct rcar_sysc_info *info;
-       const struct of_device_id *match;
-       struct rcar_pm_domains *domains;
-       struct device_node *np;
-       void __iomem *base;
-       unsigned int i;
-       int error;
-
-       np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match);
-       if (!np)
-               return -ENODEV;
-
-       info = match->data;
-
-       if (info->init) {
-               error = info->init();
-               if (error)
-                       goto out_put;
-       }
-
-       has_cpg_mstp = of_find_compatible_node(NULL, NULL,
-                                              "renesas,cpg-mstp-clocks");
-
-       base = of_iomap(np, 0);
-       if (!base) {
-               pr_warn("%pOF: Cannot map regs\n", np);
-               error = -ENOMEM;
-               goto out_put;
-       }
-
-       rcar_sysc_base = base;
-
-       /* Optional External Request Mask Register */
-       rcar_sysc_extmask_offs = info->extmask_offs;
-       rcar_sysc_extmask_val = info->extmask_val;
-
-       domains = kzalloc(sizeof(*domains), GFP_KERNEL);
-       if (!domains) {
-               error = -ENOMEM;
-               goto out_put;
-       }
-
-       domains->onecell_data.domains = domains->domains;
-       domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains);
-       rcar_sysc_onecell_data = &domains->onecell_data;
-
-       for (i = 0; i < info->num_areas; i++) {
-               const struct rcar_sysc_area *area = &info->areas[i];
-               struct rcar_sysc_pd *pd;
-               size_t n;
-
-               if (!area->name) {
-                       /* Skip NULLified area */
-                       continue;
-               }
-
-               n = strlen(area->name) + 1;
-               pd = kzalloc(sizeof(*pd) + n, GFP_KERNEL);
-               if (!pd) {
-                       error = -ENOMEM;
-                       goto out_put;
-               }
-
-               memcpy(pd->name, area->name, n);
-               pd->genpd.name = pd->name;
-               pd->ch.chan_offs = area->chan_offs;
-               pd->ch.chan_bit = area->chan_bit;
-               pd->ch.isr_bit = area->isr_bit;
-               pd->flags = area->flags;
-
-               error = rcar_sysc_pd_setup(pd);
-               if (error)
-                       goto out_put;
-
-               domains->domains[area->isr_bit] = &pd->genpd;
-
-               if (area->parent < 0)
-                       continue;
-
-               error = pm_genpd_add_subdomain(domains->domains[area->parent],
-                                              &pd->genpd);
-               if (error) {
-                       pr_warn("Failed to add PM subdomain %s to parent %u\n",
-                               area->name, area->parent);
-                       goto out_put;
-               }
-       }
-
-       error = of_genpd_add_provider_onecell(np, &domains->onecell_data);
-       if (!error)
-               fwnode_dev_initialized(of_fwnode_handle(np), true);
-
-out_put:
-       of_node_put(np);
-       return error;
-}
-early_initcall(rcar_sysc_pd_init);
-
-void __init rcar_sysc_nullify(struct rcar_sysc_area *areas,
-                             unsigned int num_areas, u8 id)
-{
-       unsigned int i;
-
-       for (i = 0; i < num_areas; i++)
-               if (areas[i].isr_bit == id) {
-                       areas[i].name = NULL;
-                       return;
-               }
-}
-
-#ifdef CONFIG_ARCH_R8A7779
-static int rcar_sysc_power_cpu(unsigned int idx, bool on)
-{
-       struct generic_pm_domain *genpd;
-       struct rcar_sysc_pd *pd;
-       unsigned int i;
-
-       if (!rcar_sysc_onecell_data)
-               return -ENODEV;
-
-       for (i = 0; i < rcar_sysc_onecell_data->num_domains; i++) {
-               genpd = rcar_sysc_onecell_data->domains[i];
-               if (!genpd)
-                       continue;
-
-               pd = to_rcar_pd(genpd);
-               if (!(pd->flags & PD_CPU) || pd->ch.chan_bit != idx)
-                       continue;
-
-               return rcar_sysc_power(&pd->ch, on);
-       }
-
-       return -ENOENT;
-}
-
-int rcar_sysc_power_down_cpu(unsigned int cpu)
-{
-       return rcar_sysc_power_cpu(cpu, false);
-}
-
-int rcar_sysc_power_up_cpu(unsigned int cpu)
-{
-       return rcar_sysc_power_cpu(cpu, true);
-}
-#endif /* CONFIG_ARCH_R8A7779 */
diff --git a/drivers/genpd/renesas/rcar-sysc.h b/drivers/genpd/renesas/rcar-sysc.h
deleted file mode 100644 (file)
index 266c599..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Renesas R-Car System Controller
- *
- * Copyright (C) 2016 Glider bvba
- */
-#ifndef __SOC_RENESAS_RCAR_SYSC_H__
-#define __SOC_RENESAS_RCAR_SYSC_H__
-
-#include <linux/types.h>
-
-
-/*
- * Power Domain flags
- */
-#define PD_CPU         BIT(0)  /* Area contains main CPU core */
-#define PD_SCU         BIT(1)  /* Area contains SCU and L2 cache */
-#define PD_NO_CR       BIT(2)  /* Area lacks PWR{ON,OFF}CR registers */
-
-#define PD_CPU_CR      PD_CPU            /* CPU area has CR (R-Car H1) */
-#define PD_CPU_NOCR    PD_CPU | PD_NO_CR /* CPU area lacks CR (R-Car Gen2/3) */
-#define PD_ALWAYS_ON   PD_NO_CR          /* Always-on area */
-
-
-/*
- * Description of a Power Area
- */
-
-struct rcar_sysc_area {
-       const char *name;
-       u16 chan_offs;          /* Offset of PWRSR register for this area */
-       u8 chan_bit;            /* Bit in PWR* (except for PWRUP in PWRSR) */
-       u8 isr_bit;             /* Bit in SYSCI*R */
-       s8 parent;              /* -1 if none */
-       u8 flags;               /* See PD_* */
-};
-
-
-/*
- * SoC-specific Power Area Description
- */
-
-struct rcar_sysc_info {
-       int (*init)(void);      /* Optional */
-       const struct rcar_sysc_area *areas;
-       unsigned int num_areas;
-       /* Optional External Request Mask Register */
-       u32 extmask_offs;       /* SYSCEXTMASK register offset */
-       u32 extmask_val;        /* SYSCEXTMASK register mask value */
-};
-
-extern const struct rcar_sysc_info r8a7742_sysc_info;
-extern const struct rcar_sysc_info r8a7743_sysc_info;
-extern const struct rcar_sysc_info r8a7745_sysc_info;
-extern const struct rcar_sysc_info r8a77470_sysc_info;
-extern const struct rcar_sysc_info r8a774a1_sysc_info;
-extern const struct rcar_sysc_info r8a774b1_sysc_info;
-extern const struct rcar_sysc_info r8a774c0_sysc_info;
-extern const struct rcar_sysc_info r8a774e1_sysc_info;
-extern const struct rcar_sysc_info r8a7779_sysc_info;
-extern const struct rcar_sysc_info r8a7790_sysc_info;
-extern const struct rcar_sysc_info r8a7791_sysc_info;
-extern const struct rcar_sysc_info r8a7792_sysc_info;
-extern const struct rcar_sysc_info r8a7794_sysc_info;
-extern struct rcar_sysc_info r8a7795_sysc_info;
-extern const struct rcar_sysc_info r8a77960_sysc_info;
-extern const struct rcar_sysc_info r8a77961_sysc_info;
-extern const struct rcar_sysc_info r8a77965_sysc_info;
-extern const struct rcar_sysc_info r8a77970_sysc_info;
-extern const struct rcar_sysc_info r8a77980_sysc_info;
-extern const struct rcar_sysc_info r8a77990_sysc_info;
-extern const struct rcar_sysc_info r8a77995_sysc_info;
-
-
-    /*
-     * Helpers for fixing up power area tables depending on SoC revision
-     */
-
-extern void rcar_sysc_nullify(struct rcar_sysc_area *areas,
-                             unsigned int num_areas, u8 id);
-
-#endif /* __SOC_RENESAS_RCAR_SYSC_H__ */
diff --git a/drivers/genpd/renesas/rmobile-sysc.c b/drivers/genpd/renesas/rmobile-sysc.c
deleted file mode 100644 (file)
index 912daad..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * rmobile power management support
- *
- * Copyright (C) 2012  Renesas Solutions Corp.
- * Copyright (C) 2012  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
- * Copyright (C) 2014  Glider bvba
- *
- * based on pm-sh7372.c
- *  Copyright (C) 2011 Magnus Damm
- */
-#include <linux/clk/renesas.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/pm.h>
-#include <linux/pm_clock.h>
-#include <linux/pm_domain.h>
-#include <linux/slab.h>
-
-/* SYSC */
-#define SPDCR          0x08    /* SYS Power Down Control Register */
-#define SWUCR          0x14    /* SYS Wakeup Control Register */
-#define PSTR           0x80    /* Power Status Register */
-
-#define PSTR_RETRIES   100
-#define PSTR_DELAY_US  10
-
-struct rmobile_pm_domain {
-       struct generic_pm_domain genpd;
-       struct dev_power_governor *gov;
-       int (*suspend)(void);
-       void __iomem *base;
-       unsigned int bit_shift;
-};
-
-static inline
-struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d)
-{
-       return container_of(d, struct rmobile_pm_domain, genpd);
-}
-
-static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
-{
-       struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd);
-       unsigned int mask = BIT(rmobile_pd->bit_shift);
-       u32 val;
-
-       if (rmobile_pd->suspend) {
-               int ret = rmobile_pd->suspend();
-
-               if (ret)
-                       return ret;
-       }
-
-       if (readl(rmobile_pd->base + PSTR) & mask) {
-               writel(mask, rmobile_pd->base + SPDCR);
-
-               readl_poll_timeout_atomic(rmobile_pd->base + SPDCR, val,
-                                         !(val & mask), 0, PSTR_RETRIES);
-       }
-
-       pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", genpd->name, mask,
-                readl(rmobile_pd->base + PSTR));
-
-       return 0;
-}
-
-static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd)
-{
-       unsigned int val, mask = BIT(rmobile_pd->bit_shift);
-       int ret = 0;
-
-       if (readl(rmobile_pd->base + PSTR) & mask)
-               return ret;
-
-       writel(mask, rmobile_pd->base + SWUCR);
-
-       ret = readl_poll_timeout_atomic(rmobile_pd->base + SWUCR, val,
-                                       (val & mask), PSTR_DELAY_US,
-                                       PSTR_RETRIES * PSTR_DELAY_US);
-
-       pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
-                rmobile_pd->genpd.name, mask,
-                readl(rmobile_pd->base + PSTR));
-
-       return ret;
-}
-
-static int rmobile_pd_power_up(struct generic_pm_domain *genpd)
-{
-       return __rmobile_pd_power_up(to_rmobile_pd(genpd));
-}
-
-static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
-{
-       struct generic_pm_domain *genpd = &rmobile_pd->genpd;
-       struct dev_power_governor *gov = rmobile_pd->gov;
-
-       genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
-       genpd->attach_dev = cpg_mstp_attach_dev;
-       genpd->detach_dev = cpg_mstp_detach_dev;
-
-       if (!(genpd->flags & GENPD_FLAG_ALWAYS_ON)) {
-               genpd->power_off = rmobile_pd_power_down;
-               genpd->power_on = rmobile_pd_power_up;
-               __rmobile_pd_power_up(rmobile_pd);
-       }
-
-       pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
-}
-
-static int rmobile_pd_suspend_console(void)
-{
-       /*
-        * Serial consoles make use of SCIF hardware located in this domain,
-        * hence keep the power domain on if "no_console_suspend" is set.
-        */
-       return console_suspend_enabled ? 0 : -EBUSY;
-}
-
-enum pd_types {
-       PD_NORMAL,
-       PD_CPU,
-       PD_CONSOLE,
-       PD_DEBUG,
-       PD_MEMCTL,
-};
-
-#define MAX_NUM_SPECIAL_PDS    16
-
-static struct special_pd {
-       struct device_node *pd;
-       enum pd_types type;
-} special_pds[MAX_NUM_SPECIAL_PDS] __initdata;
-
-static unsigned int num_special_pds __initdata;
-
-static const struct of_device_id special_ids[] __initconst = {
-       { .compatible = "arm,coresight-etm3x", .data = (void *)PD_DEBUG },
-       { .compatible = "renesas,dbsc-r8a73a4", .data = (void *)PD_MEMCTL, },
-       { .compatible = "renesas,dbsc3-r8a7740", .data = (void *)PD_MEMCTL, },
-       { .compatible = "renesas,sbsc-sh73a0", .data = (void *)PD_MEMCTL, },
-       { /* sentinel */ },
-};
-
-static void __init add_special_pd(struct device_node *np, enum pd_types type)
-{
-       unsigned int i;
-       struct device_node *pd;
-
-       pd = of_parse_phandle(np, "power-domains", 0);
-       if (!pd)
-               return;
-
-       for (i = 0; i < num_special_pds; i++)
-               if (pd == special_pds[i].pd && type == special_pds[i].type) {
-                       of_node_put(pd);
-                       return;
-               }
-
-       if (num_special_pds == ARRAY_SIZE(special_pds)) {
-               pr_warn("Too many special PM domains\n");
-               of_node_put(pd);
-               return;
-       }
-
-       pr_debug("Special PM domain %pOFn type %d for %pOF\n", pd, type, np);
-
-       special_pds[num_special_pds].pd = pd;
-       special_pds[num_special_pds].type = type;
-       num_special_pds++;
-}
-
-static void __init get_special_pds(void)
-{
-       struct device_node *np;
-       const struct of_device_id *id;
-
-       /* PM domains containing CPUs */
-       for_each_of_cpu_node(np)
-               add_special_pd(np, PD_CPU);
-
-       /* PM domain containing console */
-       if (of_stdout)
-               add_special_pd(of_stdout, PD_CONSOLE);
-
-       /* PM domains containing other special devices */
-       for_each_matching_node_and_match(np, special_ids, &id)
-               add_special_pd(np, (enum pd_types)id->data);
-}
-
-static void __init put_special_pds(void)
-{
-       unsigned int i;
-
-       for (i = 0; i < num_special_pds; i++)
-               of_node_put(special_pds[i].pd);
-}
-
-static enum pd_types __init pd_type(const struct device_node *pd)
-{
-       unsigned int i;
-
-       for (i = 0; i < num_special_pds; i++)
-               if (pd == special_pds[i].pd)
-                       return special_pds[i].type;
-
-       return PD_NORMAL;
-}
-
-static void __init rmobile_setup_pm_domain(struct device_node *np,
-                                          struct rmobile_pm_domain *pd)
-{
-       const char *name = pd->genpd.name;
-
-       switch (pd_type(np)) {
-       case PD_CPU:
-               /*
-                * This domain contains the CPU core and therefore it should
-                * only be turned off if the CPU is not in use.
-                */
-               pr_debug("PM domain %s contains CPU\n", name);
-               pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
-               break;
-
-       case PD_CONSOLE:
-               pr_debug("PM domain %s contains serial console\n", name);
-               pd->gov = &pm_domain_always_on_gov;
-               pd->suspend = rmobile_pd_suspend_console;
-               break;
-
-       case PD_DEBUG:
-               /*
-                * This domain contains the Coresight-ETM hardware block and
-                * therefore it should only be turned off if the debug module
-                * is not in use.
-                */
-               pr_debug("PM domain %s contains Coresight-ETM\n", name);
-               pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
-               break;
-
-       case PD_MEMCTL:
-               /*
-                * This domain contains a memory-controller and therefore it
-                * should only be turned off if memory is not in use.
-                */
-               pr_debug("PM domain %s contains MEMCTL\n", name);
-               pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
-               break;
-
-       case PD_NORMAL:
-               if (pd->bit_shift == ~0) {
-                       /* Top-level always-on domain */
-                       pr_debug("PM domain %s is always-on domain\n", name);
-                       pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
-               }
-               break;
-       }
-
-       rmobile_init_pm_domain(pd);
-}
-
-static int __init rmobile_add_pm_domains(void __iomem *base,
-                                        struct device_node *parent,
-                                        struct generic_pm_domain *genpd_parent)
-{
-       struct device_node *np;
-
-       for_each_child_of_node(parent, np) {
-               struct rmobile_pm_domain *pd;
-               u32 idx = ~0;
-
-               if (of_property_read_u32(np, "reg", &idx)) {
-                       /* always-on domain */
-               }
-
-               pd = kzalloc(sizeof(*pd), GFP_KERNEL);
-               if (!pd) {
-                       of_node_put(np);
-                       return -ENOMEM;
-               }
-
-               pd->genpd.name = np->name;
-               pd->base = base;
-               pd->bit_shift = idx;
-
-               rmobile_setup_pm_domain(np, pd);
-               if (genpd_parent)
-                       pm_genpd_add_subdomain(genpd_parent, &pd->genpd);
-               of_genpd_add_provider_simple(np, &pd->genpd);
-
-               rmobile_add_pm_domains(base, np, &pd->genpd);
-       }
-       return 0;
-}
-
-static int __init rmobile_init_pm_domains(void)
-{
-       struct device_node *np, *pmd;
-       bool scanned = false;
-       void __iomem *base;
-       int ret = 0;
-
-       for_each_compatible_node(np, NULL, "renesas,sysc-rmobile") {
-               base = of_iomap(np, 0);
-               if (!base) {
-                       pr_warn("%pOF cannot map reg 0\n", np);
-                       continue;
-               }
-
-               pmd = of_get_child_by_name(np, "pm-domains");
-               if (!pmd) {
-                       iounmap(base);
-                       pr_warn("%pOF lacks pm-domains node\n", np);
-                       continue;
-               }
-
-               if (!scanned) {
-                       /* Find PM domains containing special blocks */
-                       get_special_pds();
-                       scanned = true;
-               }
-
-               ret = rmobile_add_pm_domains(base, pmd, NULL);
-               of_node_put(pmd);
-               if (ret) {
-                       of_node_put(np);
-                       break;
-               }
-
-               fwnode_dev_initialized(of_fwnode_handle(np), true);
-       }
-
-       put_special_pds();
-
-       return ret;
-}
-
-core_initcall(rmobile_init_pm_domains);
diff --git a/drivers/genpd/rockchip/Makefile b/drivers/genpd/rockchip/Makefile
deleted file mode 100644 (file)
index 8fb9d88..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_ROCKCHIP_PM_DOMAINS)      += pm-domains.o
diff --git a/drivers/genpd/rockchip/pm-domains.c b/drivers/genpd/rockchip/pm-domains.c
deleted file mode 100644 (file)
index d5d3ecb..0000000
+++ /dev/null
@@ -1,1396 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Rockchip Generic power domain support.
- *
- * Copyright (c) 2015 ROCKCHIP, Co. Ltd.
- */
-
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/err.h>
-#include <linux/mutex.h>
-#include <linux/pm_clock.h>
-#include <linux/pm_domain.h>
-#include <linux/of_address.h>
-#include <linux/of_clk.h>
-#include <linux/of_platform.h>
-#include <linux/clk.h>
-#include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
-#include <soc/rockchip/pm_domains.h>
-#include <dt-bindings/power/px30-power.h>
-#include <dt-bindings/power/rockchip,rv1126-power.h>
-#include <dt-bindings/power/rk3036-power.h>
-#include <dt-bindings/power/rk3066-power.h>
-#include <dt-bindings/power/rk3128-power.h>
-#include <dt-bindings/power/rk3188-power.h>
-#include <dt-bindings/power/rk3228-power.h>
-#include <dt-bindings/power/rk3288-power.h>
-#include <dt-bindings/power/rk3328-power.h>
-#include <dt-bindings/power/rk3366-power.h>
-#include <dt-bindings/power/rk3368-power.h>
-#include <dt-bindings/power/rk3399-power.h>
-#include <dt-bindings/power/rk3568-power.h>
-#include <dt-bindings/power/rk3588-power.h>
-
-struct rockchip_domain_info {
-       const char *name;
-       int pwr_mask;
-       int status_mask;
-       int req_mask;
-       int idle_mask;
-       int ack_mask;
-       bool active_wakeup;
-       int pwr_w_mask;
-       int req_w_mask;
-       int mem_status_mask;
-       int repair_status_mask;
-       u32 pwr_offset;
-       u32 mem_offset;
-       u32 req_offset;
-};
-
-struct rockchip_pmu_info {
-       u32 pwr_offset;
-       u32 status_offset;
-       u32 req_offset;
-       u32 idle_offset;
-       u32 ack_offset;
-       u32 mem_pwr_offset;
-       u32 chain_status_offset;
-       u32 mem_status_offset;
-       u32 repair_status_offset;
-
-       u32 core_pwrcnt_offset;
-       u32 gpu_pwrcnt_offset;
-
-       unsigned int core_power_transition_time;
-       unsigned int gpu_power_transition_time;
-
-       int num_domains;
-       const struct rockchip_domain_info *domain_info;
-};
-
-#define MAX_QOS_REGS_NUM       5
-#define QOS_PRIORITY           0x08
-#define QOS_MODE               0x0c
-#define QOS_BANDWIDTH          0x10
-#define QOS_SATURATION         0x14
-#define QOS_EXTCONTROL         0x18
-
-struct rockchip_pm_domain {
-       struct generic_pm_domain genpd;
-       const struct rockchip_domain_info *info;
-       struct rockchip_pmu *pmu;
-       int num_qos;
-       struct regmap **qos_regmap;
-       u32 *qos_save_regs[MAX_QOS_REGS_NUM];
-       int num_clks;
-       struct clk_bulk_data *clks;
-};
-
-struct rockchip_pmu {
-       struct device *dev;
-       struct regmap *regmap;
-       const struct rockchip_pmu_info *info;
-       struct mutex mutex; /* mutex lock for pmu */
-       struct genpd_onecell_data genpd_data;
-       struct generic_pm_domain *domains[];
-};
-
-#define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd)
-
-#define DOMAIN(_name, pwr, status, req, idle, ack, wakeup)     \
-{                                                      \
-       .name = _name,                          \
-       .pwr_mask = (pwr),                              \
-       .status_mask = (status),                        \
-       .req_mask = (req),                              \
-       .idle_mask = (idle),                            \
-       .ack_mask = (ack),                              \
-       .active_wakeup = (wakeup),                      \
-}
-
-#define DOMAIN_M(_name, pwr, status, req, idle, ack, wakeup)   \
-{                                                      \
-       .name = _name,                          \
-       .pwr_w_mask = (pwr) << 16,                      \
-       .pwr_mask = (pwr),                              \
-       .status_mask = (status),                        \
-       .req_w_mask = (req) << 16,                      \
-       .req_mask = (req),                              \
-       .idle_mask = (idle),                            \
-       .ack_mask = (ack),                              \
-       .active_wakeup = wakeup,                        \
-}
-
-#define DOMAIN_M_O_R(_name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, ack, wakeup)     \
-{                                                      \
-       .name = _name,                                  \
-       .pwr_offset = p_offset,                         \
-       .pwr_w_mask = (pwr) << 16,                      \
-       .pwr_mask = (pwr),                              \
-       .status_mask = (status),                        \
-       .mem_offset = m_offset,                         \
-       .mem_status_mask = (m_status),                  \
-       .repair_status_mask = (r_status),               \
-       .req_offset = r_offset,                         \
-       .req_w_mask = (req) << 16,                      \
-       .req_mask = (req),                              \
-       .idle_mask = (idle),                            \
-       .ack_mask = (ack),                              \
-       .active_wakeup = wakeup,                        \
-}
-
-#define DOMAIN_RK3036(_name, req, ack, idle, wakeup)           \
-{                                                      \
-       .name = _name,                          \
-       .req_mask = (req),                              \
-       .req_w_mask = (req) << 16,                      \
-       .ack_mask = (ack),                              \
-       .idle_mask = (idle),                            \
-       .active_wakeup = wakeup,                        \
-}
-
-#define DOMAIN_PX30(name, pwr, status, req, wakeup)            \
-       DOMAIN_M(name, pwr, status, req, (req) << 16, req, wakeup)
-
-#define DOMAIN_RV1126(name, pwr, req, idle, wakeup)            \
-       DOMAIN_M(name, pwr, pwr, req, idle, idle, wakeup)
-
-#define DOMAIN_RK3288(name, pwr, status, req, wakeup)          \
-       DOMAIN(name, pwr, status, req, req, (req) << 16, wakeup)
-
-#define DOMAIN_RK3328(name, pwr, status, req, wakeup)          \
-       DOMAIN_M(name, pwr, pwr, req, (req) << 10, req, wakeup)
-
-#define DOMAIN_RK3368(name, pwr, status, req, wakeup)          \
-       DOMAIN(name, pwr, status, req, (req) << 16, req, wakeup)
-
-#define DOMAIN_RK3399(name, pwr, status, req, wakeup)          \
-       DOMAIN(name, pwr, status, req, req, req, wakeup)
-
-#define DOMAIN_RK3568(name, pwr, req, wakeup)          \
-       DOMAIN_M(name, pwr, pwr, req, req, req, wakeup)
-
-/*
- * Dynamic Memory Controller may need to coordinate with us -- see
- * rockchip_pmu_block().
- *
- * dmc_pmu_mutex protects registration-time races, so DMC driver doesn't try to
- * block() while we're initializing the PMU.
- */
-static DEFINE_MUTEX(dmc_pmu_mutex);
-static struct rockchip_pmu *dmc_pmu;
-
-/*
- * Block PMU transitions and make sure they don't interfere with ARM Trusted
- * Firmware operations. There are two conflicts, noted in the comments below.
- *
- * Caller must unblock PMU transitions via rockchip_pmu_unblock().
- */
-int rockchip_pmu_block(void)
-{
-       struct rockchip_pmu *pmu;
-       struct generic_pm_domain *genpd;
-       struct rockchip_pm_domain *pd;
-       int i, ret;
-
-       mutex_lock(&dmc_pmu_mutex);
-
-       /* No PMU (yet)? Then we just block rockchip_pmu_probe(). */
-       if (!dmc_pmu)
-               return 0;
-       pmu = dmc_pmu;
-
-       /*
-        * mutex blocks all idle transitions: we can't touch the
-        * PMU_BUS_IDLE_REQ (our ".idle_offset") register while ARM Trusted
-        * Firmware might be using it.
-        */
-       mutex_lock(&pmu->mutex);
-
-       /*
-        * Power domain clocks: Per Rockchip, we *must* keep certain clocks
-        * enabled for the duration of power-domain transitions. Most
-        * transitions are handled by this driver, but some cases (in
-        * particular, DRAM DVFS / memory-controller idle) must be handled by
-        * firmware. Firmware can handle most clock management via a special
-        * "ungate" register (PMU_CRU_GATEDIS_CON0), but unfortunately, this
-        * doesn't handle PLLs. We can assist this transition by doing the
-        * clock management on behalf of firmware.
-        */
-       for (i = 0; i < pmu->genpd_data.num_domains; i++) {
-               genpd = pmu->genpd_data.domains[i];
-               if (genpd) {
-                       pd = to_rockchip_pd(genpd);
-                       ret = clk_bulk_enable(pd->num_clks, pd->clks);
-                       if (ret < 0) {
-                               dev_err(pmu->dev,
-                                       "failed to enable clks for domain '%s': %d\n",
-                                       genpd->name, ret);
-                               goto err;
-                       }
-               }
-       }
-
-       return 0;
-
-err:
-       for (i = i - 1; i >= 0; i--) {
-               genpd = pmu->genpd_data.domains[i];
-               if (genpd) {
-                       pd = to_rockchip_pd(genpd);
-                       clk_bulk_disable(pd->num_clks, pd->clks);
-               }
-       }
-       mutex_unlock(&pmu->mutex);
-       mutex_unlock(&dmc_pmu_mutex);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(rockchip_pmu_block);
-
-/* Unblock PMU transitions. */
-void rockchip_pmu_unblock(void)
-{
-       struct rockchip_pmu *pmu;
-       struct generic_pm_domain *genpd;
-       struct rockchip_pm_domain *pd;
-       int i;
-
-       if (dmc_pmu) {
-               pmu = dmc_pmu;
-               for (i = 0; i < pmu->genpd_data.num_domains; i++) {
-                       genpd = pmu->genpd_data.domains[i];
-                       if (genpd) {
-                               pd = to_rockchip_pd(genpd);
-                               clk_bulk_disable(pd->num_clks, pd->clks);
-                       }
-               }
-
-               mutex_unlock(&pmu->mutex);
-       }
-
-       mutex_unlock(&dmc_pmu_mutex);
-}
-EXPORT_SYMBOL_GPL(rockchip_pmu_unblock);
-
-#define DOMAIN_RK3588(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, wakeup)  \
-       DOMAIN_M_O_R(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, idle, wakeup)
-
-static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
-{
-       struct rockchip_pmu *pmu = pd->pmu;
-       const struct rockchip_domain_info *pd_info = pd->info;
-       unsigned int val;
-
-       regmap_read(pmu->regmap, pmu->info->idle_offset, &val);
-       return (val & pd_info->idle_mask) == pd_info->idle_mask;
-}
-
-static unsigned int rockchip_pmu_read_ack(struct rockchip_pmu *pmu)
-{
-       unsigned int val;
-
-       regmap_read(pmu->regmap, pmu->info->ack_offset, &val);
-       return val;
-}
-
-static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
-                                        bool idle)
-{
-       const struct rockchip_domain_info *pd_info = pd->info;
-       struct generic_pm_domain *genpd = &pd->genpd;
-       struct rockchip_pmu *pmu = pd->pmu;
-       u32 pd_req_offset = pd_info->req_offset;
-       unsigned int target_ack;
-       unsigned int val;
-       bool is_idle;
-       int ret;
-
-       if (pd_info->req_mask == 0)
-               return 0;
-       else if (pd_info->req_w_mask)
-               regmap_write(pmu->regmap, pmu->info->req_offset + pd_req_offset,
-                            idle ? (pd_info->req_mask | pd_info->req_w_mask) :
-                            pd_info->req_w_mask);
-       else
-               regmap_update_bits(pmu->regmap, pmu->info->req_offset + pd_req_offset,
-                                  pd_info->req_mask, idle ? -1U : 0);
-
-       wmb();
-
-       /* Wait util idle_ack = 1 */
-       target_ack = idle ? pd_info->ack_mask : 0;
-       ret = readx_poll_timeout_atomic(rockchip_pmu_read_ack, pmu, val,
-                                       (val & pd_info->ack_mask) == target_ack,
-                                       0, 10000);
-       if (ret) {
-               dev_err(pmu->dev,
-                       "failed to get ack on domain '%s', val=0x%x\n",
-                       genpd->name, val);
-               return ret;
-       }
-
-       ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_idle, pd,
-                                       is_idle, is_idle == idle, 0, 10000);
-       if (ret) {
-               dev_err(pmu->dev,
-                       "failed to set idle on domain '%s', val=%d\n",
-                       genpd->name, is_idle);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd)
-{
-       int i;
-
-       for (i = 0; i < pd->num_qos; i++) {
-               regmap_read(pd->qos_regmap[i],
-                           QOS_PRIORITY,
-                           &pd->qos_save_regs[0][i]);
-               regmap_read(pd->qos_regmap[i],
-                           QOS_MODE,
-                           &pd->qos_save_regs[1][i]);
-               regmap_read(pd->qos_regmap[i],
-                           QOS_BANDWIDTH,
-                           &pd->qos_save_regs[2][i]);
-               regmap_read(pd->qos_regmap[i],
-                           QOS_SATURATION,
-                           &pd->qos_save_regs[3][i]);
-               regmap_read(pd->qos_regmap[i],
-                           QOS_EXTCONTROL,
-                           &pd->qos_save_regs[4][i]);
-       }
-       return 0;
-}
-
-static int rockchip_pmu_restore_qos(struct rockchip_pm_domain *pd)
-{
-       int i;
-
-       for (i = 0; i < pd->num_qos; i++) {
-               regmap_write(pd->qos_regmap[i],
-                            QOS_PRIORITY,
-                            pd->qos_save_regs[0][i]);
-               regmap_write(pd->qos_regmap[i],
-                            QOS_MODE,
-                            pd->qos_save_regs[1][i]);
-               regmap_write(pd->qos_regmap[i],
-                            QOS_BANDWIDTH,
-                            pd->qos_save_regs[2][i]);
-               regmap_write(pd->qos_regmap[i],
-                            QOS_SATURATION,
-                            pd->qos_save_regs[3][i]);
-               regmap_write(pd->qos_regmap[i],
-                            QOS_EXTCONTROL,
-                            pd->qos_save_regs[4][i]);
-       }
-
-       return 0;
-}
-
-static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
-{
-       struct rockchip_pmu *pmu = pd->pmu;
-       unsigned int val;
-
-       if (pd->info->repair_status_mask) {
-               regmap_read(pmu->regmap, pmu->info->repair_status_offset, &val);
-               /* 1'b1: power on, 1'b0: power off */
-               return val & pd->info->repair_status_mask;
-       }
-
-       /* check idle status for idle-only domains */
-       if (pd->info->status_mask == 0)
-               return !rockchip_pmu_domain_is_idle(pd);
-
-       regmap_read(pmu->regmap, pmu->info->status_offset, &val);
-
-       /* 1'b0: power on, 1'b1: power off */
-       return !(val & pd->info->status_mask);
-}
-
-static bool rockchip_pmu_domain_is_mem_on(struct rockchip_pm_domain *pd)
-{
-       struct rockchip_pmu *pmu = pd->pmu;
-       unsigned int val;
-
-       regmap_read(pmu->regmap,
-                   pmu->info->mem_status_offset + pd->info->mem_offset, &val);
-
-       /* 1'b0: power on, 1'b1: power off */
-       return !(val & pd->info->mem_status_mask);
-}
-
-static bool rockchip_pmu_domain_is_chain_on(struct rockchip_pm_domain *pd)
-{
-       struct rockchip_pmu *pmu = pd->pmu;
-       unsigned int val;
-
-       regmap_read(pmu->regmap,
-                   pmu->info->chain_status_offset + pd->info->mem_offset, &val);
-
-       /* 1'b1: power on, 1'b0: power off */
-       return val & pd->info->mem_status_mask;
-}
-
-static int rockchip_pmu_domain_mem_reset(struct rockchip_pm_domain *pd)
-{
-       struct rockchip_pmu *pmu = pd->pmu;
-       struct generic_pm_domain *genpd = &pd->genpd;
-       bool is_on;
-       int ret = 0;
-
-       ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_chain_on, pd, is_on,
-                                       is_on == true, 0, 10000);
-       if (ret) {
-               dev_err(pmu->dev,
-                       "failed to get chain status '%s', target_on=1, val=%d\n",
-                       genpd->name, is_on);
-               goto error;
-       }
-
-       udelay(20);
-
-       regmap_write(pmu->regmap, pmu->info->mem_pwr_offset + pd->info->pwr_offset,
-                    (pd->info->pwr_mask | pd->info->pwr_w_mask));
-       wmb();
-
-       ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_mem_on, pd, is_on,
-                                       is_on == false, 0, 10000);
-       if (ret) {
-               dev_err(pmu->dev,
-                       "failed to get mem status '%s', target_on=0, val=%d\n",
-                       genpd->name, is_on);
-               goto error;
-       }
-
-       regmap_write(pmu->regmap, pmu->info->mem_pwr_offset + pd->info->pwr_offset,
-                    pd->info->pwr_w_mask);
-       wmb();
-
-       ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_mem_on, pd, is_on,
-                                       is_on == true, 0, 10000);
-       if (ret) {
-               dev_err(pmu->dev,
-                       "failed to get mem status '%s', target_on=1, val=%d\n",
-                       genpd->name, is_on);
-       }
-
-error:
-       return ret;
-}
-
-static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
-                                            bool on)
-{
-       struct rockchip_pmu *pmu = pd->pmu;
-       struct generic_pm_domain *genpd = &pd->genpd;
-       u32 pd_pwr_offset = pd->info->pwr_offset;
-       bool is_on, is_mem_on = false;
-
-       if (pd->info->pwr_mask == 0)
-               return;
-
-       if (on && pd->info->mem_status_mask)
-               is_mem_on = rockchip_pmu_domain_is_mem_on(pd);
-
-       if (pd->info->pwr_w_mask)
-               regmap_write(pmu->regmap, pmu->info->pwr_offset + pd_pwr_offset,
-                            on ? pd->info->pwr_w_mask :
-                            (pd->info->pwr_mask | pd->info->pwr_w_mask));
-       else
-               regmap_update_bits(pmu->regmap, pmu->info->pwr_offset + pd_pwr_offset,
-                                  pd->info->pwr_mask, on ? 0 : -1U);
-
-       wmb();
-
-       if (is_mem_on && rockchip_pmu_domain_mem_reset(pd))
-               return;
-
-       if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
-                                     is_on == on, 0, 10000)) {
-               dev_err(pmu->dev,
-                       "failed to set domain '%s', val=%d\n",
-                       genpd->name, is_on);
-               return;
-       }
-}
-
-static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
-{
-       struct rockchip_pmu *pmu = pd->pmu;
-       int ret;
-
-       mutex_lock(&pmu->mutex);
-
-       if (rockchip_pmu_domain_is_on(pd) != power_on) {
-               ret = clk_bulk_enable(pd->num_clks, pd->clks);
-               if (ret < 0) {
-                       dev_err(pmu->dev, "failed to enable clocks\n");
-                       mutex_unlock(&pmu->mutex);
-                       return ret;
-               }
-
-               if (!power_on) {
-                       rockchip_pmu_save_qos(pd);
-
-                       /* if powering down, idle request to NIU first */
-                       rockchip_pmu_set_idle_request(pd, true);
-               }
-
-               rockchip_do_pmu_set_power_domain(pd, power_on);
-
-               if (power_on) {
-                       /* if powering up, leave idle mode */
-                       rockchip_pmu_set_idle_request(pd, false);
-
-                       rockchip_pmu_restore_qos(pd);
-               }
-
-               clk_bulk_disable(pd->num_clks, pd->clks);
-       }
-
-       mutex_unlock(&pmu->mutex);
-       return 0;
-}
-
-static int rockchip_pd_power_on(struct generic_pm_domain *domain)
-{
-       struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
-
-       return rockchip_pd_power(pd, true);
-}
-
-static int rockchip_pd_power_off(struct generic_pm_domain *domain)
-{
-       struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
-
-       return rockchip_pd_power(pd, false);
-}
-
-static int rockchip_pd_attach_dev(struct generic_pm_domain *genpd,
-                                 struct device *dev)
-{
-       struct clk *clk;
-       int i;
-       int error;
-
-       dev_dbg(dev, "attaching to power domain '%s'\n", genpd->name);
-
-       error = pm_clk_create(dev);
-       if (error) {
-               dev_err(dev, "pm_clk_create failed %d\n", error);
-               return error;
-       }
-
-       i = 0;
-       while ((clk = of_clk_get(dev->of_node, i++)) && !IS_ERR(clk)) {
-               dev_dbg(dev, "adding clock '%pC' to list of PM clocks\n", clk);
-               error = pm_clk_add_clk(dev, clk);
-               if (error) {
-                       dev_err(dev, "pm_clk_add_clk failed %d\n", error);
-                       clk_put(clk);
-                       pm_clk_destroy(dev);
-                       return error;
-               }
-       }
-
-       return 0;
-}
-
-static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd,
-                                  struct device *dev)
-{
-       dev_dbg(dev, "detaching from power domain '%s'\n", genpd->name);
-
-       pm_clk_destroy(dev);
-}
-
-static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
-                                     struct device_node *node)
-{
-       const struct rockchip_domain_info *pd_info;
-       struct rockchip_pm_domain *pd;
-       struct device_node *qos_node;
-       int i, j;
-       u32 id;
-       int error;
-
-       error = of_property_read_u32(node, "reg", &id);
-       if (error) {
-               dev_err(pmu->dev,
-                       "%pOFn: failed to retrieve domain id (reg): %d\n",
-                       node, error);
-               return -EINVAL;
-       }
-
-       if (id >= pmu->info->num_domains) {
-               dev_err(pmu->dev, "%pOFn: invalid domain id %d\n",
-                       node, id);
-               return -EINVAL;
-       }
-       /* RK3588 has domains with two parents (RKVDEC0/RKVDEC1) */
-       if (pmu->genpd_data.domains[id])
-               return 0;
-
-       pd_info = &pmu->info->domain_info[id];
-       if (!pd_info) {
-               dev_err(pmu->dev, "%pOFn: undefined domain id %d\n",
-                       node, id);
-               return -EINVAL;
-       }
-
-       pd = devm_kzalloc(pmu->dev, sizeof(*pd), GFP_KERNEL);
-       if (!pd)
-               return -ENOMEM;
-
-       pd->info = pd_info;
-       pd->pmu = pmu;
-
-       pd->num_clks = of_clk_get_parent_count(node);
-       if (pd->num_clks > 0) {
-               pd->clks = devm_kcalloc(pmu->dev, pd->num_clks,
-                                       sizeof(*pd->clks), GFP_KERNEL);
-               if (!pd->clks)
-                       return -ENOMEM;
-       } else {
-               dev_dbg(pmu->dev, "%pOFn: doesn't have clocks: %d\n",
-                       node, pd->num_clks);
-               pd->num_clks = 0;
-       }
-
-       for (i = 0; i < pd->num_clks; i++) {
-               pd->clks[i].clk = of_clk_get(node, i);
-               if (IS_ERR(pd->clks[i].clk)) {
-                       error = PTR_ERR(pd->clks[i].clk);
-                       dev_err(pmu->dev,
-                               "%pOFn: failed to get clk at index %d: %d\n",
-                               node, i, error);
-                       return error;
-               }
-       }
-
-       error = clk_bulk_prepare(pd->num_clks, pd->clks);
-       if (error)
-               goto err_put_clocks;
-
-       pd->num_qos = of_count_phandle_with_args(node, "pm_qos",
-                                                NULL);
-
-       if (pd->num_qos > 0) {
-               pd->qos_regmap = devm_kcalloc(pmu->dev, pd->num_qos,
-                                             sizeof(*pd->qos_regmap),
-                                             GFP_KERNEL);
-               if (!pd->qos_regmap) {
-                       error = -ENOMEM;
-                       goto err_unprepare_clocks;
-               }
-
-               for (j = 0; j < MAX_QOS_REGS_NUM; j++) {
-                       pd->qos_save_regs[j] = devm_kcalloc(pmu->dev,
-                                                           pd->num_qos,
-                                                           sizeof(u32),
-                                                           GFP_KERNEL);
-                       if (!pd->qos_save_regs[j]) {
-                               error = -ENOMEM;
-                               goto err_unprepare_clocks;
-                       }
-               }
-
-               for (j = 0; j < pd->num_qos; j++) {
-                       qos_node = of_parse_phandle(node, "pm_qos", j);
-                       if (!qos_node) {
-                               error = -ENODEV;
-                               goto err_unprepare_clocks;
-                       }
-                       pd->qos_regmap[j] = syscon_node_to_regmap(qos_node);
-                       if (IS_ERR(pd->qos_regmap[j])) {
-                               error = -ENODEV;
-                               of_node_put(qos_node);
-                               goto err_unprepare_clocks;
-                       }
-                       of_node_put(qos_node);
-               }
-       }
-
-       if (pd->info->name)
-               pd->genpd.name = pd->info->name;
-       else
-               pd->genpd.name = kbasename(node->full_name);
-       pd->genpd.power_off = rockchip_pd_power_off;
-       pd->genpd.power_on = rockchip_pd_power_on;
-       pd->genpd.attach_dev = rockchip_pd_attach_dev;
-       pd->genpd.detach_dev = rockchip_pd_detach_dev;
-       pd->genpd.flags = GENPD_FLAG_PM_CLK;
-       if (pd_info->active_wakeup)
-               pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
-       pm_genpd_init(&pd->genpd, NULL,
-                     !rockchip_pmu_domain_is_on(pd) ||
-                     (pd->info->mem_status_mask && !rockchip_pmu_domain_is_mem_on(pd)));
-
-       pmu->genpd_data.domains[id] = &pd->genpd;
-       return 0;
-
-err_unprepare_clocks:
-       clk_bulk_unprepare(pd->num_clks, pd->clks);
-err_put_clocks:
-       clk_bulk_put(pd->num_clks, pd->clks);
-       return error;
-}
-
-static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd)
-{
-       int ret;
-
-       /*
-        * We're in the error cleanup already, so we only complain,
-        * but won't emit another error on top of the original one.
-        */
-       ret = pm_genpd_remove(&pd->genpd);
-       if (ret < 0)
-               dev_err(pd->pmu->dev, "failed to remove domain '%s' : %d - state may be inconsistent\n",
-                       pd->genpd.name, ret);
-
-       clk_bulk_unprepare(pd->num_clks, pd->clks);
-       clk_bulk_put(pd->num_clks, pd->clks);
-
-       /* protect the zeroing of pm->num_clks */
-       mutex_lock(&pd->pmu->mutex);
-       pd->num_clks = 0;
-       mutex_unlock(&pd->pmu->mutex);
-
-       /* devm will free our memory */
-}
-
-static void rockchip_pm_domain_cleanup(struct rockchip_pmu *pmu)
-{
-       struct generic_pm_domain *genpd;
-       struct rockchip_pm_domain *pd;
-       int i;
-
-       for (i = 0; i < pmu->genpd_data.num_domains; i++) {
-               genpd = pmu->genpd_data.domains[i];
-               if (genpd) {
-                       pd = to_rockchip_pd(genpd);
-                       rockchip_pm_remove_one_domain(pd);
-               }
-       }
-
-       /* devm will free our memory */
-}
-
-static void rockchip_configure_pd_cnt(struct rockchip_pmu *pmu,
-                                     u32 domain_reg_offset,
-                                     unsigned int count)
-{
-       /* First configure domain power down transition count ... */
-       regmap_write(pmu->regmap, domain_reg_offset, count);
-       /* ... and then power up count. */
-       regmap_write(pmu->regmap, domain_reg_offset + 4, count);
-}
-
-static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu,
-                                    struct device_node *parent)
-{
-       struct device_node *np;
-       struct generic_pm_domain *child_domain, *parent_domain;
-       int error;
-
-       for_each_child_of_node(parent, np) {
-               u32 idx;
-
-               error = of_property_read_u32(parent, "reg", &idx);
-               if (error) {
-                       dev_err(pmu->dev,
-                               "%pOFn: failed to retrieve domain id (reg): %d\n",
-                               parent, error);
-                       goto err_out;
-               }
-               parent_domain = pmu->genpd_data.domains[idx];
-
-               error = rockchip_pm_add_one_domain(pmu, np);
-               if (error) {
-                       dev_err(pmu->dev, "failed to handle node %pOFn: %d\n",
-                               np, error);
-                       goto err_out;
-               }
-
-               error = of_property_read_u32(np, "reg", &idx);
-               if (error) {
-                       dev_err(pmu->dev,
-                               "%pOFn: failed to retrieve domain id (reg): %d\n",
-                               np, error);
-                       goto err_out;
-               }
-               child_domain = pmu->genpd_data.domains[idx];
-
-               error = pm_genpd_add_subdomain(parent_domain, child_domain);
-               if (error) {
-                       dev_err(pmu->dev, "%s failed to add subdomain %s: %d\n",
-                               parent_domain->name, child_domain->name, error);
-                       goto err_out;
-               } else {
-                       dev_dbg(pmu->dev, "%s add subdomain: %s\n",
-                               parent_domain->name, child_domain->name);
-               }
-
-               rockchip_pm_add_subdomain(pmu, np);
-       }
-
-       return 0;
-
-err_out:
-       of_node_put(np);
-       return error;
-}
-
-static int rockchip_pm_domain_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       struct device_node *node;
-       struct device *parent;
-       struct rockchip_pmu *pmu;
-       const struct of_device_id *match;
-       const struct rockchip_pmu_info *pmu_info;
-       int error;
-
-       if (!np) {
-               dev_err(dev, "device tree node not found\n");
-               return -ENODEV;
-       }
-
-       match = of_match_device(dev->driver->of_match_table, dev);
-       if (!match || !match->data) {
-               dev_err(dev, "missing pmu data\n");
-               return -EINVAL;
-       }
-
-       pmu_info = match->data;
-
-       pmu = devm_kzalloc(dev,
-                          struct_size(pmu, domains, pmu_info->num_domains),
-                          GFP_KERNEL);
-       if (!pmu)
-               return -ENOMEM;
-
-       pmu->dev = &pdev->dev;
-       mutex_init(&pmu->mutex);
-
-       pmu->info = pmu_info;
-
-       pmu->genpd_data.domains = pmu->domains;
-       pmu->genpd_data.num_domains = pmu_info->num_domains;
-
-       parent = dev->parent;
-       if (!parent) {
-               dev_err(dev, "no parent for syscon devices\n");
-               return -ENODEV;
-       }
-
-       pmu->regmap = syscon_node_to_regmap(parent->of_node);
-       if (IS_ERR(pmu->regmap)) {
-               dev_err(dev, "no regmap available\n");
-               return PTR_ERR(pmu->regmap);
-       }
-
-       /*
-        * Configure power up and down transition delays for CORE
-        * and GPU domains.
-        */
-       if (pmu_info->core_power_transition_time)
-               rockchip_configure_pd_cnt(pmu, pmu_info->core_pwrcnt_offset,
-                                       pmu_info->core_power_transition_time);
-       if (pmu_info->gpu_pwrcnt_offset)
-               rockchip_configure_pd_cnt(pmu, pmu_info->gpu_pwrcnt_offset,
-                                       pmu_info->gpu_power_transition_time);
-
-       error = -ENODEV;
-
-       /*
-        * Prevent any rockchip_pmu_block() from racing with the remainder of
-        * setup (clocks, register initialization).
-        */
-       mutex_lock(&dmc_pmu_mutex);
-
-       for_each_available_child_of_node(np, node) {
-               error = rockchip_pm_add_one_domain(pmu, node);
-               if (error) {
-                       dev_err(dev, "failed to handle node %pOFn: %d\n",
-                               node, error);
-                       of_node_put(node);
-                       goto err_out;
-               }
-
-               error = rockchip_pm_add_subdomain(pmu, node);
-               if (error < 0) {
-                       dev_err(dev, "failed to handle subdomain node %pOFn: %d\n",
-                               node, error);
-                       of_node_put(node);
-                       goto err_out;
-               }
-       }
-
-       if (error) {
-               dev_dbg(dev, "no power domains defined\n");
-               goto err_out;
-       }
-
-       error = of_genpd_add_provider_onecell(np, &pmu->genpd_data);
-       if (error) {
-               dev_err(dev, "failed to add provider: %d\n", error);
-               goto err_out;
-       }
-
-       /* We only expect one PMU. */
-       if (!WARN_ON_ONCE(dmc_pmu))
-               dmc_pmu = pmu;
-
-       mutex_unlock(&dmc_pmu_mutex);
-
-       return 0;
-
-err_out:
-       rockchip_pm_domain_cleanup(pmu);
-       mutex_unlock(&dmc_pmu_mutex);
-       return error;
-}
-
-static const struct rockchip_domain_info px30_pm_domains[] = {
-       [PX30_PD_USB]           = DOMAIN_PX30("usb",      BIT(5),  BIT(5),  BIT(10), false),
-       [PX30_PD_SDCARD]        = DOMAIN_PX30("sdcard",   BIT(8),  BIT(8),  BIT(9),  false),
-       [PX30_PD_GMAC]          = DOMAIN_PX30("gmac",     BIT(10), BIT(10), BIT(6),  false),
-       [PX30_PD_MMC_NAND]      = DOMAIN_PX30("mmc_nand", BIT(11), BIT(11), BIT(5),  false),
-       [PX30_PD_VPU]           = DOMAIN_PX30("vpu",      BIT(12), BIT(12), BIT(14), false),
-       [PX30_PD_VO]            = DOMAIN_PX30("vo",       BIT(13), BIT(13), BIT(7),  false),
-       [PX30_PD_VI]            = DOMAIN_PX30("vi",       BIT(14), BIT(14), BIT(8),  false),
-       [PX30_PD_GPU]           = DOMAIN_PX30("gpu",      BIT(15), BIT(15), BIT(2),  false),
-};
-
-static const struct rockchip_domain_info rv1126_pm_domains[] = {
-       [RV1126_PD_VEPU]        = DOMAIN_RV1126("vepu", BIT(2),  BIT(9),  BIT(9), false),
-       [RV1126_PD_VI]          = DOMAIN_RV1126("vi", BIT(4),  BIT(6),  BIT(6),  false),
-       [RV1126_PD_VO]          = DOMAIN_RV1126("vo", BIT(5),  BIT(7),  BIT(7),  false),
-       [RV1126_PD_ISPP]        = DOMAIN_RV1126("ispp", BIT(1), BIT(8), BIT(8),  false),
-       [RV1126_PD_VDPU]        = DOMAIN_RV1126("vdpu", BIT(3), BIT(10), BIT(10), false),
-       [RV1126_PD_NVM]         = DOMAIN_RV1126("nvm", BIT(7), BIT(11), BIT(11),  false),
-       [RV1126_PD_SDIO]        = DOMAIN_RV1126("sdio", BIT(8), BIT(13), BIT(13),  false),
-       [RV1126_PD_USB]         = DOMAIN_RV1126("usb", BIT(9), BIT(15), BIT(15),  false),
-};
-
-static const struct rockchip_domain_info rk3036_pm_domains[] = {
-       [RK3036_PD_MSCH]        = DOMAIN_RK3036("msch", BIT(14), BIT(23), BIT(30), true),
-       [RK3036_PD_CORE]        = DOMAIN_RK3036("core", BIT(13), BIT(17), BIT(24), false),
-       [RK3036_PD_PERI]        = DOMAIN_RK3036("peri", BIT(12), BIT(18), BIT(25), false),
-       [RK3036_PD_VIO]         = DOMAIN_RK3036("vio",  BIT(11), BIT(19), BIT(26), false),
-       [RK3036_PD_VPU]         = DOMAIN_RK3036("vpu",  BIT(10), BIT(20), BIT(27), false),
-       [RK3036_PD_GPU]         = DOMAIN_RK3036("gpu",  BIT(9),  BIT(21), BIT(28), false),
-       [RK3036_PD_SYS]         = DOMAIN_RK3036("sys",  BIT(8),  BIT(22), BIT(29), false),
-};
-
-static const struct rockchip_domain_info rk3066_pm_domains[] = {
-       [RK3066_PD_GPU]         = DOMAIN("gpu",   BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false),
-       [RK3066_PD_VIDEO]       = DOMAIN("video", BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false),
-       [RK3066_PD_VIO]         = DOMAIN("vio",   BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false),
-       [RK3066_PD_PERI]        = DOMAIN("peri",  BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false),
-       [RK3066_PD_CPU]         = DOMAIN("cpu",   0,      BIT(5), BIT(1), BIT(26), BIT(31), false),
-};
-
-static const struct rockchip_domain_info rk3128_pm_domains[] = {
-       [RK3128_PD_CORE]        = DOMAIN_RK3288("core",  BIT(0), BIT(0), BIT(4), false),
-       [RK3128_PD_MSCH]        = DOMAIN_RK3288("msch",  0,      0,      BIT(6), true),
-       [RK3128_PD_VIO]         = DOMAIN_RK3288("vio",   BIT(3), BIT(3), BIT(2), false),
-       [RK3128_PD_VIDEO]       = DOMAIN_RK3288("video", BIT(2), BIT(2), BIT(1), false),
-       [RK3128_PD_GPU]         = DOMAIN_RK3288("gpu",   BIT(1), BIT(1), BIT(3), false),
-};
-
-static const struct rockchip_domain_info rk3188_pm_domains[] = {
-       [RK3188_PD_GPU]         = DOMAIN("gpu",   BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false),
-       [RK3188_PD_VIDEO]       = DOMAIN("video", BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false),
-       [RK3188_PD_VIO]         = DOMAIN("vio",   BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false),
-       [RK3188_PD_PERI]        = DOMAIN("peri",  BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false),
-       [RK3188_PD_CPU]         = DOMAIN("cpu",   BIT(5), BIT(5), BIT(1), BIT(26), BIT(31), false),
-};
-
-static const struct rockchip_domain_info rk3228_pm_domains[] = {
-       [RK3228_PD_CORE]        = DOMAIN_RK3036("core", BIT(0),  BIT(0),  BIT(16), true),
-       [RK3228_PD_MSCH]        = DOMAIN_RK3036("msch", BIT(1),  BIT(1),  BIT(17), true),
-       [RK3228_PD_BUS]         = DOMAIN_RK3036("bus",  BIT(2),  BIT(2),  BIT(18), true),
-       [RK3228_PD_SYS]         = DOMAIN_RK3036("sys",  BIT(3),  BIT(3),  BIT(19), true),
-       [RK3228_PD_VIO]         = DOMAIN_RK3036("vio",  BIT(4),  BIT(4),  BIT(20), false),
-       [RK3228_PD_VOP]         = DOMAIN_RK3036("vop",  BIT(5),  BIT(5),  BIT(21), false),
-       [RK3228_PD_VPU]         = DOMAIN_RK3036("vpu",  BIT(6),  BIT(6),  BIT(22), false),
-       [RK3228_PD_RKVDEC]      = DOMAIN_RK3036("vdec", BIT(7),  BIT(7),  BIT(23), false),
-       [RK3228_PD_GPU]         = DOMAIN_RK3036("gpu",  BIT(8),  BIT(8),  BIT(24), false),
-       [RK3228_PD_PERI]        = DOMAIN_RK3036("peri", BIT(9),  BIT(9),  BIT(25), true),
-       [RK3228_PD_GMAC]        = DOMAIN_RK3036("gmac", BIT(10), BIT(10), BIT(26), false),
-};
-
-static const struct rockchip_domain_info rk3288_pm_domains[] = {
-       [RK3288_PD_VIO]         = DOMAIN_RK3288("vio",   BIT(7),  BIT(7),  BIT(4), false),
-       [RK3288_PD_HEVC]        = DOMAIN_RK3288("hevc",  BIT(14), BIT(10), BIT(9), false),
-       [RK3288_PD_VIDEO]       = DOMAIN_RK3288("video", BIT(8),  BIT(8),  BIT(3), false),
-       [RK3288_PD_GPU]         = DOMAIN_RK3288("gpu",   BIT(9),  BIT(9),  BIT(2), false),
-};
-
-static const struct rockchip_domain_info rk3328_pm_domains[] = {
-       [RK3328_PD_CORE]        = DOMAIN_RK3328("core",  0, BIT(0), BIT(0), false),
-       [RK3328_PD_GPU]         = DOMAIN_RK3328("gpu",   0, BIT(1), BIT(1), false),
-       [RK3328_PD_BUS]         = DOMAIN_RK3328("bus",   0, BIT(2), BIT(2), true),
-       [RK3328_PD_MSCH]        = DOMAIN_RK3328("msch",  0, BIT(3), BIT(3), true),
-       [RK3328_PD_PERI]        = DOMAIN_RK3328("peri",  0, BIT(4), BIT(4), true),
-       [RK3328_PD_VIDEO]       = DOMAIN_RK3328("video", 0, BIT(5), BIT(5), false),
-       [RK3328_PD_HEVC]        = DOMAIN_RK3328("hevc",  0, BIT(6), BIT(6), false),
-       [RK3328_PD_VIO]         = DOMAIN_RK3328("vio",   0, BIT(8), BIT(8), false),
-       [RK3328_PD_VPU]         = DOMAIN_RK3328("vpu",   0, BIT(9), BIT(9), false),
-};
-
-static const struct rockchip_domain_info rk3366_pm_domains[] = {
-       [RK3366_PD_PERI]        = DOMAIN_RK3368("peri",   BIT(10), BIT(10), BIT(6), true),
-       [RK3366_PD_VIO]         = DOMAIN_RK3368("vio",    BIT(14), BIT(14), BIT(8), false),
-       [RK3366_PD_VIDEO]       = DOMAIN_RK3368("video",  BIT(13), BIT(13), BIT(7), false),
-       [RK3366_PD_RKVDEC]      = DOMAIN_RK3368("vdec",   BIT(11), BIT(11), BIT(7), false),
-       [RK3366_PD_WIFIBT]      = DOMAIN_RK3368("wifibt", BIT(8),  BIT(8),  BIT(9), false),
-       [RK3366_PD_VPU]         = DOMAIN_RK3368("vpu",    BIT(12), BIT(12), BIT(7), false),
-       [RK3366_PD_GPU]         = DOMAIN_RK3368("gpu",    BIT(15), BIT(15), BIT(2), false),
-};
-
-static const struct rockchip_domain_info rk3368_pm_domains[] = {
-       [RK3368_PD_PERI]        = DOMAIN_RK3368("peri",  BIT(13), BIT(12), BIT(6), true),
-       [RK3368_PD_VIO]         = DOMAIN_RK3368("vio",   BIT(15), BIT(14), BIT(8), false),
-       [RK3368_PD_VIDEO]       = DOMAIN_RK3368("video", BIT(14), BIT(13), BIT(7), false),
-       [RK3368_PD_GPU_0]       = DOMAIN_RK3368("gpu_0", BIT(16), BIT(15), BIT(2), false),
-       [RK3368_PD_GPU_1]       = DOMAIN_RK3368("gpu_1", BIT(17), BIT(16), BIT(2), false),
-};
-
-static const struct rockchip_domain_info rk3399_pm_domains[] = {
-       [RK3399_PD_TCPD0]       = DOMAIN_RK3399("tcpd0",     BIT(8),  BIT(8),  0,       false),
-       [RK3399_PD_TCPD1]       = DOMAIN_RK3399("tcpd1",     BIT(9),  BIT(9),  0,       false),
-       [RK3399_PD_CCI]         = DOMAIN_RK3399("cci",       BIT(10), BIT(10), 0,       true),
-       [RK3399_PD_CCI0]        = DOMAIN_RK3399("cci0",      0,       0,       BIT(15), true),
-       [RK3399_PD_CCI1]        = DOMAIN_RK3399("cci1",      0,       0,       BIT(16), true),
-       [RK3399_PD_PERILP]      = DOMAIN_RK3399("perilp",    BIT(11), BIT(11), BIT(1),  true),
-       [RK3399_PD_PERIHP]      = DOMAIN_RK3399("perihp",    BIT(12), BIT(12), BIT(2),  true),
-       [RK3399_PD_CENTER]      = DOMAIN_RK3399("center",    BIT(13), BIT(13), BIT(14), true),
-       [RK3399_PD_VIO]         = DOMAIN_RK3399("vio",       BIT(14), BIT(14), BIT(17), false),
-       [RK3399_PD_GPU]         = DOMAIN_RK3399("gpu",       BIT(15), BIT(15), BIT(0),  false),
-       [RK3399_PD_VCODEC]      = DOMAIN_RK3399("vcodec",    BIT(16), BIT(16), BIT(3),  false),
-       [RK3399_PD_VDU]         = DOMAIN_RK3399("vdu",       BIT(17), BIT(17), BIT(4),  false),
-       [RK3399_PD_RGA]         = DOMAIN_RK3399("rga",       BIT(18), BIT(18), BIT(5),  false),
-       [RK3399_PD_IEP]         = DOMAIN_RK3399("iep",       BIT(19), BIT(19), BIT(6),  false),
-       [RK3399_PD_VO]          = DOMAIN_RK3399("vo",        BIT(20), BIT(20), 0,       false),
-       [RK3399_PD_VOPB]        = DOMAIN_RK3399("vopb",      0,       0,       BIT(7),  false),
-       [RK3399_PD_VOPL]        = DOMAIN_RK3399("vopl",      0,       0,       BIT(8),  false),
-       [RK3399_PD_ISP0]        = DOMAIN_RK3399("isp0",      BIT(22), BIT(22), BIT(9),  false),
-       [RK3399_PD_ISP1]        = DOMAIN_RK3399("isp1",      BIT(23), BIT(23), BIT(10), false),
-       [RK3399_PD_HDCP]        = DOMAIN_RK3399("hdcp",      BIT(24), BIT(24), BIT(11), false),
-       [RK3399_PD_GMAC]        = DOMAIN_RK3399("gmac",      BIT(25), BIT(25), BIT(23), true),
-       [RK3399_PD_EMMC]        = DOMAIN_RK3399("emmc",      BIT(26), BIT(26), BIT(24), true),
-       [RK3399_PD_USB3]        = DOMAIN_RK3399("usb3",      BIT(27), BIT(27), BIT(12), true),
-       [RK3399_PD_EDP]         = DOMAIN_RK3399("edp",       BIT(28), BIT(28), BIT(22), false),
-       [RK3399_PD_GIC]         = DOMAIN_RK3399("gic",       BIT(29), BIT(29), BIT(27), true),
-       [RK3399_PD_SD]          = DOMAIN_RK3399("sd",        BIT(30), BIT(30), BIT(28), true),
-       [RK3399_PD_SDIOAUDIO]   = DOMAIN_RK3399("sdioaudio", BIT(31), BIT(31), BIT(29), true),
-};
-
-static const struct rockchip_domain_info rk3568_pm_domains[] = {
-       [RK3568_PD_NPU]         = DOMAIN_RK3568("npu",  BIT(1), BIT(2),  false),
-       [RK3568_PD_GPU]         = DOMAIN_RK3568("gpu",  BIT(0), BIT(1),  false),
-       [RK3568_PD_VI]          = DOMAIN_RK3568("vi",   BIT(6), BIT(3),  false),
-       [RK3568_PD_VO]          = DOMAIN_RK3568("vo",   BIT(7), BIT(4),  false),
-       [RK3568_PD_RGA]         = DOMAIN_RK3568("rga",  BIT(5), BIT(5),  false),
-       [RK3568_PD_VPU]         = DOMAIN_RK3568("vpu",  BIT(2), BIT(6),  false),
-       [RK3568_PD_RKVDEC]      = DOMAIN_RK3568("vdec", BIT(4), BIT(8),  false),
-       [RK3568_PD_RKVENC]      = DOMAIN_RK3568("venc", BIT(3), BIT(7),  false),
-       [RK3568_PD_PIPE]        = DOMAIN_RK3568("pipe", BIT(8), BIT(11), false),
-};
-
-static const struct rockchip_domain_info rk3588_pm_domains[] = {
-       [RK3588_PD_GPU]         = DOMAIN_RK3588("gpu",     0x0, BIT(0),  0,       0x0, 0,       BIT(1),  0x0, BIT(0),  BIT(0),  false),
-       [RK3588_PD_NPU]         = DOMAIN_RK3588("npu",     0x0, BIT(1),  BIT(1),  0x0, 0,       0,       0x0, 0,       0,       false),
-       [RK3588_PD_VCODEC]      = DOMAIN_RK3588("vcodec",  0x0, BIT(2),  BIT(2),  0x0, 0,       0,       0x0, 0,       0,       false),
-       [RK3588_PD_NPUTOP]      = DOMAIN_RK3588("nputop",  0x0, BIT(3),  0,       0x0, BIT(11), BIT(2),  0x0, BIT(1),  BIT(1),  false),
-       [RK3588_PD_NPU1]        = DOMAIN_RK3588("npu1",    0x0, BIT(4),  0,       0x0, BIT(12), BIT(3),  0x0, BIT(2),  BIT(2),  false),
-       [RK3588_PD_NPU2]        = DOMAIN_RK3588("npu2",    0x0, BIT(5),  0,       0x0, BIT(13), BIT(4),  0x0, BIT(3),  BIT(3),  false),
-       [RK3588_PD_VENC0]       = DOMAIN_RK3588("venc0",   0x0, BIT(6),  0,       0x0, BIT(14), BIT(5),  0x0, BIT(4),  BIT(4),  false),
-       [RK3588_PD_VENC1]       = DOMAIN_RK3588("venc1",   0x0, BIT(7),  0,       0x0, BIT(15), BIT(6),  0x0, BIT(5),  BIT(5),  false),
-       [RK3588_PD_RKVDEC0]     = DOMAIN_RK3588("rkvdec0", 0x0, BIT(8),  0,       0x0, BIT(16), BIT(7),  0x0, BIT(6),  BIT(6),  false),
-       [RK3588_PD_RKVDEC1]     = DOMAIN_RK3588("rkvdec1", 0x0, BIT(9),  0,       0x0, BIT(17), BIT(8),  0x0, BIT(7),  BIT(7),  false),
-       [RK3588_PD_VDPU]        = DOMAIN_RK3588("vdpu",    0x0, BIT(10), 0,       0x0, BIT(18), BIT(9),  0x0, BIT(8),  BIT(8),  false),
-       [RK3588_PD_RGA30]       = DOMAIN_RK3588("rga30",   0x0, BIT(11), 0,       0x0, BIT(19), BIT(10), 0x0, 0,       0,       false),
-       [RK3588_PD_AV1]         = DOMAIN_RK3588("av1",     0x0, BIT(12), 0,       0x0, BIT(20), BIT(11), 0x0, BIT(9),  BIT(9),  false),
-       [RK3588_PD_VI]          = DOMAIN_RK3588("vi",      0x0, BIT(13), 0,       0x0, BIT(21), BIT(12), 0x0, BIT(10), BIT(10), false),
-       [RK3588_PD_FEC]         = DOMAIN_RK3588("fec",     0x0, BIT(14), 0,       0x0, BIT(22), BIT(13), 0x0, 0,       0,       false),
-       [RK3588_PD_ISP1]        = DOMAIN_RK3588("isp1",    0x0, BIT(15), 0,       0x0, BIT(23), BIT(14), 0x0, BIT(11), BIT(11), false),
-       [RK3588_PD_RGA31]       = DOMAIN_RK3588("rga31",   0x4, BIT(0),  0,       0x0, BIT(24), BIT(15), 0x0, BIT(12), BIT(12), false),
-       [RK3588_PD_VOP]         = DOMAIN_RK3588("vop",     0x4, BIT(1),  0,       0x0, BIT(25), BIT(16), 0x0, BIT(13) | BIT(14), BIT(13) | BIT(14), false),
-       [RK3588_PD_VO0]         = DOMAIN_RK3588("vo0",     0x4, BIT(2),  0,       0x0, BIT(26), BIT(17), 0x0, BIT(15), BIT(15), false),
-       [RK3588_PD_VO1]         = DOMAIN_RK3588("vo1",     0x4, BIT(3),  0,       0x0, BIT(27), BIT(18), 0x4, BIT(0),  BIT(16), false),
-       [RK3588_PD_AUDIO]       = DOMAIN_RK3588("audio",   0x4, BIT(4),  0,       0x0, BIT(28), BIT(19), 0x4, BIT(1),  BIT(17), false),
-       [RK3588_PD_PHP]         = DOMAIN_RK3588("php",     0x4, BIT(5),  0,       0x0, BIT(29), BIT(20), 0x4, BIT(5),  BIT(21), false),
-       [RK3588_PD_GMAC]        = DOMAIN_RK3588("gmac",    0x4, BIT(6),  0,       0x0, BIT(30), BIT(21), 0x0, 0,       0,       false),
-       [RK3588_PD_PCIE]        = DOMAIN_RK3588("pcie",    0x4, BIT(7),  0,       0x0, BIT(31), BIT(22), 0x0, 0,       0,       true),
-       [RK3588_PD_NVM]         = DOMAIN_RK3588("nvm",     0x4, BIT(8),  BIT(24), 0x4, 0,       0,       0x4, BIT(2),  BIT(18), false),
-       [RK3588_PD_NVM0]        = DOMAIN_RK3588("nvm0",    0x4, BIT(9),  0,       0x4, BIT(1),  BIT(23), 0x0, 0,       0,       false),
-       [RK3588_PD_SDIO]        = DOMAIN_RK3588("sdio",    0x4, BIT(10), 0,       0x4, BIT(2),  BIT(24), 0x4, BIT(3),  BIT(19), false),
-       [RK3588_PD_USB]         = DOMAIN_RK3588("usb",     0x4, BIT(11), 0,       0x4, BIT(3),  BIT(25), 0x4, BIT(4),  BIT(20), true),
-       [RK3588_PD_SDMMC]       = DOMAIN_RK3588("sdmmc",   0x4, BIT(13), 0,       0x4, BIT(5),  BIT(26), 0x0, 0,       0,       false),
-};
-
-static const struct rockchip_pmu_info px30_pmu = {
-       .pwr_offset = 0x18,
-       .status_offset = 0x20,
-       .req_offset = 0x64,
-       .idle_offset = 0x6c,
-       .ack_offset = 0x6c,
-
-       .num_domains = ARRAY_SIZE(px30_pm_domains),
-       .domain_info = px30_pm_domains,
-};
-
-static const struct rockchip_pmu_info rk3036_pmu = {
-       .req_offset = 0x148,
-       .idle_offset = 0x14c,
-       .ack_offset = 0x14c,
-
-       .num_domains = ARRAY_SIZE(rk3036_pm_domains),
-       .domain_info = rk3036_pm_domains,
-};
-
-static const struct rockchip_pmu_info rk3066_pmu = {
-       .pwr_offset = 0x08,
-       .status_offset = 0x0c,
-       .req_offset = 0x38, /* PMU_MISC_CON1 */
-       .idle_offset = 0x0c,
-       .ack_offset = 0x0c,
-
-       .num_domains = ARRAY_SIZE(rk3066_pm_domains),
-       .domain_info = rk3066_pm_domains,
-};
-
-static const struct rockchip_pmu_info rk3128_pmu = {
-       .pwr_offset = 0x04,
-       .status_offset = 0x08,
-       .req_offset = 0x0c,
-       .idle_offset = 0x10,
-       .ack_offset = 0x10,
-
-       .num_domains = ARRAY_SIZE(rk3128_pm_domains),
-       .domain_info = rk3128_pm_domains,
-};
-
-static const struct rockchip_pmu_info rk3188_pmu = {
-       .pwr_offset = 0x08,
-       .status_offset = 0x0c,
-       .req_offset = 0x38, /* PMU_MISC_CON1 */
-       .idle_offset = 0x0c,
-       .ack_offset = 0x0c,
-
-       .num_domains = ARRAY_SIZE(rk3188_pm_domains),
-       .domain_info = rk3188_pm_domains,
-};
-
-static const struct rockchip_pmu_info rk3228_pmu = {
-       .req_offset = 0x40c,
-       .idle_offset = 0x488,
-       .ack_offset = 0x488,
-
-       .num_domains = ARRAY_SIZE(rk3228_pm_domains),
-       .domain_info = rk3228_pm_domains,
-};
-
-static const struct rockchip_pmu_info rk3288_pmu = {
-       .pwr_offset = 0x08,
-       .status_offset = 0x0c,
-       .req_offset = 0x10,
-       .idle_offset = 0x14,
-       .ack_offset = 0x14,
-
-       .core_pwrcnt_offset = 0x34,
-       .gpu_pwrcnt_offset = 0x3c,
-
-       .core_power_transition_time = 24, /* 1us */
-       .gpu_power_transition_time = 24, /* 1us */
-
-       .num_domains = ARRAY_SIZE(rk3288_pm_domains),
-       .domain_info = rk3288_pm_domains,
-};
-
-static const struct rockchip_pmu_info rk3328_pmu = {
-       .req_offset = 0x414,
-       .idle_offset = 0x484,
-       .ack_offset = 0x484,
-
-       .num_domains = ARRAY_SIZE(rk3328_pm_domains),
-       .domain_info = rk3328_pm_domains,
-};
-
-static const struct rockchip_pmu_info rk3366_pmu = {
-       .pwr_offset = 0x0c,
-       .status_offset = 0x10,
-       .req_offset = 0x3c,
-       .idle_offset = 0x40,
-       .ack_offset = 0x40,
-
-       .core_pwrcnt_offset = 0x48,
-       .gpu_pwrcnt_offset = 0x50,
-
-       .core_power_transition_time = 24,
-       .gpu_power_transition_time = 24,
-
-       .num_domains = ARRAY_SIZE(rk3366_pm_domains),
-       .domain_info = rk3366_pm_domains,
-};
-
-static const struct rockchip_pmu_info rk3368_pmu = {
-       .pwr_offset = 0x0c,
-       .status_offset = 0x10,
-       .req_offset = 0x3c,
-       .idle_offset = 0x40,
-       .ack_offset = 0x40,
-
-       .core_pwrcnt_offset = 0x48,
-       .gpu_pwrcnt_offset = 0x50,
-
-       .core_power_transition_time = 24,
-       .gpu_power_transition_time = 24,
-
-       .num_domains = ARRAY_SIZE(rk3368_pm_domains),
-       .domain_info = rk3368_pm_domains,
-};
-
-static const struct rockchip_pmu_info rk3399_pmu = {
-       .pwr_offset = 0x14,
-       .status_offset = 0x18,
-       .req_offset = 0x60,
-       .idle_offset = 0x64,
-       .ack_offset = 0x68,
-
-       /* ARM Trusted Firmware manages power transition times */
-
-       .num_domains = ARRAY_SIZE(rk3399_pm_domains),
-       .domain_info = rk3399_pm_domains,
-};
-
-static const struct rockchip_pmu_info rk3568_pmu = {
-       .pwr_offset = 0xa0,
-       .status_offset = 0x98,
-       .req_offset = 0x50,
-       .idle_offset = 0x68,
-       .ack_offset = 0x60,
-
-       .num_domains = ARRAY_SIZE(rk3568_pm_domains),
-       .domain_info = rk3568_pm_domains,
-};
-
-static const struct rockchip_pmu_info rk3588_pmu = {
-       .pwr_offset = 0x14c,
-       .status_offset = 0x180,
-       .req_offset = 0x10c,
-       .idle_offset = 0x120,
-       .ack_offset = 0x118,
-       .mem_pwr_offset = 0x1a0,
-       .chain_status_offset = 0x1f0,
-       .mem_status_offset = 0x1f8,
-       .repair_status_offset = 0x290,
-
-       .num_domains = ARRAY_SIZE(rk3588_pm_domains),
-       .domain_info = rk3588_pm_domains,
-};
-
-static const struct rockchip_pmu_info rv1126_pmu = {
-       .pwr_offset = 0x110,
-       .status_offset = 0x108,
-       .req_offset = 0xc0,
-       .idle_offset = 0xd8,
-       .ack_offset = 0xd0,
-
-       .num_domains = ARRAY_SIZE(rv1126_pm_domains),
-       .domain_info = rv1126_pm_domains,
-};
-
-static const struct of_device_id rockchip_pm_domain_dt_match[] = {
-       {
-               .compatible = "rockchip,px30-power-controller",
-               .data = (void *)&px30_pmu,
-       },
-       {
-               .compatible = "rockchip,rk3036-power-controller",
-               .data = (void *)&rk3036_pmu,
-       },
-       {
-               .compatible = "rockchip,rk3066-power-controller",
-               .data = (void *)&rk3066_pmu,
-       },
-       {
-               .compatible = "rockchip,rk3128-power-controller",
-               .data = (void *)&rk3128_pmu,
-       },
-       {
-               .compatible = "rockchip,rk3188-power-controller",
-               .data = (void *)&rk3188_pmu,
-       },
-       {
-               .compatible = "rockchip,rk3228-power-controller",
-               .data = (void *)&rk3228_pmu,
-       },
-       {
-               .compatible = "rockchip,rk3288-power-controller",
-               .data = (void *)&rk3288_pmu,
-       },
-       {
-               .compatible = "rockchip,rk3328-power-controller",
-               .data = (void *)&rk3328_pmu,
-       },
-       {
-               .compatible = "rockchip,rk3366-power-controller",
-               .data = (void *)&rk3366_pmu,
-       },
-       {
-               .compatible = "rockchip,rk3368-power-controller",
-               .data = (void *)&rk3368_pmu,
-       },
-       {
-               .compatible = "rockchip,rk3399-power-controller",
-               .data = (void *)&rk3399_pmu,
-       },
-       {
-               .compatible = "rockchip,rk3568-power-controller",
-               .data = (void *)&rk3568_pmu,
-       },
-       {
-               .compatible = "rockchip,rk3588-power-controller",
-               .data = (void *)&rk3588_pmu,
-       },
-       {
-               .compatible = "rockchip,rv1126-power-controller",
-               .data = (void *)&rv1126_pmu,
-       },
-       { /* sentinel */ },
-};
-
-static struct platform_driver rockchip_pm_domain_driver = {
-       .probe = rockchip_pm_domain_probe,
-       .driver = {
-               .name   = "rockchip-pm-domain",
-               .of_match_table = rockchip_pm_domain_dt_match,
-               /*
-                * We can't forcibly eject devices from the power
-                * domain, so we can't really remove power domains
-                * once they were added.
-                */
-               .suppress_bind_attrs = true,
-       },
-};
-
-static int __init rockchip_pm_domain_drv_register(void)
-{
-       return platform_driver_register(&rockchip_pm_domain_driver);
-}
-postcore_initcall(rockchip_pm_domain_drv_register);
diff --git a/drivers/genpd/samsung/Makefile b/drivers/genpd/samsung/Makefile
deleted file mode 100644 (file)
index 397aa59..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_EXYNOS_PM_DOMAINS)                += exynos-pm-domains.o
diff --git a/drivers/genpd/samsung/exynos-pm-domains.c b/drivers/genpd/samsung/exynos-pm-domains.c
deleted file mode 100644 (file)
index 9b502e8..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Exynos Generic power domain support.
-//
-// Copyright (c) 2012 Samsung Electronics Co., Ltd.
-//             http://www.samsung.com
-//
-// Implementation of Exynos specific power domain control which is used in
-// conjunction with runtime-pm. Support for both device-tree and non-device-tree
-// based power domain support is included.
-
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/pm_domain.h>
-#include <linux/delay.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/pm_runtime.h>
-
-struct exynos_pm_domain_config {
-       /* Value for LOCAL_PWR_CFG and STATUS fields for each domain */
-       u32 local_pwr_cfg;
-};
-
-/*
- * Exynos specific wrapper around the generic power domain
- */
-struct exynos_pm_domain {
-       void __iomem *base;
-       struct generic_pm_domain pd;
-       u32 local_pwr_cfg;
-};
-
-static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
-{
-       struct exynos_pm_domain *pd;
-       void __iomem *base;
-       u32 timeout, pwr;
-       char *op;
-
-       pd = container_of(domain, struct exynos_pm_domain, pd);
-       base = pd->base;
-
-       pwr = power_on ? pd->local_pwr_cfg : 0;
-       writel_relaxed(pwr, base);
-
-       /* Wait max 1ms */
-       timeout = 10;
-
-       while ((readl_relaxed(base + 0x4) & pd->local_pwr_cfg) != pwr) {
-               if (!timeout) {
-                       op = (power_on) ? "enable" : "disable";
-                       pr_err("Power domain %s %s failed\n", domain->name, op);
-                       return -ETIMEDOUT;
-               }
-               timeout--;
-               cpu_relax();
-               usleep_range(80, 100);
-       }
-
-       return 0;
-}
-
-static int exynos_pd_power_on(struct generic_pm_domain *domain)
-{
-       return exynos_pd_power(domain, true);
-}
-
-static int exynos_pd_power_off(struct generic_pm_domain *domain)
-{
-       return exynos_pd_power(domain, false);
-}
-
-static const struct exynos_pm_domain_config exynos4210_cfg = {
-       .local_pwr_cfg          = 0x7,
-};
-
-static const struct exynos_pm_domain_config exynos5433_cfg = {
-       .local_pwr_cfg          = 0xf,
-};
-
-static const struct of_device_id exynos_pm_domain_of_match[] = {
-       {
-               .compatible = "samsung,exynos4210-pd",
-               .data = &exynos4210_cfg,
-       }, {
-               .compatible = "samsung,exynos5433-pd",
-               .data = &exynos5433_cfg,
-       },
-       { },
-};
-
-static const char *exynos_get_domain_name(struct device_node *node)
-{
-       const char *name;
-
-       if (of_property_read_string(node, "label", &name) < 0)
-               name = kbasename(node->full_name);
-       return kstrdup_const(name, GFP_KERNEL);
-}
-
-static int exynos_pd_probe(struct platform_device *pdev)
-{
-       const struct exynos_pm_domain_config *pm_domain_cfg;
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       struct of_phandle_args child, parent;
-       struct exynos_pm_domain *pd;
-       int on, ret;
-
-       pm_domain_cfg = of_device_get_match_data(dev);
-       pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
-       if (!pd)
-               return -ENOMEM;
-
-       pd->pd.name = exynos_get_domain_name(np);
-       if (!pd->pd.name)
-               return -ENOMEM;
-
-       pd->base = of_iomap(np, 0);
-       if (!pd->base) {
-               kfree_const(pd->pd.name);
-               return -ENODEV;
-       }
-
-       pd->pd.power_off = exynos_pd_power_off;
-       pd->pd.power_on = exynos_pd_power_on;
-       pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg;
-
-       on = readl_relaxed(pd->base + 0x4) & pd->local_pwr_cfg;
-
-       pm_genpd_init(&pd->pd, NULL, !on);
-       ret = of_genpd_add_provider_simple(np, &pd->pd);
-
-       if (ret == 0 && of_parse_phandle_with_args(np, "power-domains",
-                                     "#power-domain-cells", 0, &parent) == 0) {
-               child.np = np;
-               child.args_count = 0;
-
-               if (of_genpd_add_subdomain(&parent, &child))
-                       pr_warn("%pOF failed to add subdomain: %pOF\n",
-                               parent.np, child.np);
-               else
-                       pr_info("%pOF has as child subdomain: %pOF.\n",
-                               parent.np, child.np);
-       }
-
-       pm_runtime_enable(dev);
-       return ret;
-}
-
-static struct platform_driver exynos_pd_driver = {
-       .probe  = exynos_pd_probe,
-       .driver = {
-               .name           = "exynos-pd",
-               .of_match_table = exynos_pm_domain_of_match,
-               .suppress_bind_attrs = true,
-       }
-};
-
-static __init int exynos4_pm_init_power_domain(void)
-{
-       return platform_driver_register(&exynos_pd_driver);
-}
-core_initcall(exynos4_pm_init_power_domain);
diff --git a/drivers/genpd/st/Makefile b/drivers/genpd/st/Makefile
deleted file mode 100644 (file)
index 8fa5f98..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_ARCH_U8500)               += ste-ux500-pm-domain.o
diff --git a/drivers/genpd/st/ste-ux500-pm-domain.c b/drivers/genpd/st/ste-ux500-pm-domain.c
deleted file mode 100644 (file)
index 3d4f111..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2014 Linaro Ltd.
- *
- * Author: Ulf Hansson <ulf.hansson@linaro.org>
- *
- * Implements PM domains using the generic PM domain for ux500.
- */
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/printk.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/of.h>
-#include <linux/pm_domain.h>
-
-#include <dt-bindings/arm/ux500_pm_domains.h>
-
-static int pd_power_off(struct generic_pm_domain *domain)
-{
-       /*
-        * Handle the gating of the PM domain regulator here.
-        *
-        * Drivers/subsystems handling devices in the PM domain needs to perform
-        * register context save/restore from their respective runtime PM
-        * callbacks, to be able to enable PM domain gating/ungating.
-        */
-       return 0;
-}
-
-static int pd_power_on(struct generic_pm_domain *domain)
-{
-       /*
-        * Handle the ungating of the PM domain regulator here.
-        *
-        * Drivers/subsystems handling devices in the PM domain needs to perform
-        * register context save/restore from their respective runtime PM
-        * callbacks, to be able to enable PM domain gating/ungating.
-        */
-       return 0;
-}
-
-static struct generic_pm_domain ux500_pm_domain_vape = {
-       .name = "VAPE",
-       .power_off = pd_power_off,
-       .power_on = pd_power_on,
-};
-
-static struct generic_pm_domain *ux500_pm_domains[NR_DOMAINS] = {
-       [DOMAIN_VAPE] = &ux500_pm_domain_vape,
-};
-
-static const struct of_device_id ux500_pm_domain_matches[] = {
-       { .compatible = "stericsson,ux500-pm-domains", },
-       { },
-};
-
-static int ux500_pm_domains_probe(struct platform_device *pdev)
-{
-       struct device_node *np = pdev->dev.of_node;
-       struct genpd_onecell_data *genpd_data;
-       int i;
-
-       if (!np)
-               return -ENODEV;
-
-       genpd_data = kzalloc(sizeof(*genpd_data), GFP_KERNEL);
-       if (!genpd_data)
-               return -ENOMEM;
-
-       genpd_data->domains = ux500_pm_domains;
-       genpd_data->num_domains = ARRAY_SIZE(ux500_pm_domains);
-
-       for (i = 0; i < ARRAY_SIZE(ux500_pm_domains); ++i)
-               pm_genpd_init(ux500_pm_domains[i], NULL, false);
-
-       of_genpd_add_provider_onecell(np, genpd_data);
-       return 0;
-}
-
-static struct platform_driver ux500_pm_domains_driver = {
-       .probe  = ux500_pm_domains_probe,
-       .driver = {
-               .name = "ux500_pm_domains",
-               .of_match_table = ux500_pm_domain_matches,
-       },
-};
-
-static int __init ux500_pm_domains_init(void)
-{
-       return platform_driver_register(&ux500_pm_domains_driver);
-}
-arch_initcall(ux500_pm_domains_init);
diff --git a/drivers/genpd/starfive/Makefile b/drivers/genpd/starfive/Makefile
deleted file mode 100644 (file)
index 975bba2..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_JH71XX_PMU)               += jh71xx-pmu.o
diff --git a/drivers/genpd/starfive/jh71xx-pmu.c b/drivers/genpd/starfive/jh71xx-pmu.c
deleted file mode 100644 (file)
index 7d5f50d..0000000
+++ /dev/null
@@ -1,383 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * StarFive JH71XX PMU (Power Management Unit) Controller Driver
- *
- * Copyright (C) 2022 StarFive Technology Co., Ltd.
- */
-
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <dt-bindings/power/starfive,jh7110-pmu.h>
-
-/* register offset */
-#define JH71XX_PMU_SW_TURN_ON_POWER    0x0C
-#define JH71XX_PMU_SW_TURN_OFF_POWER   0x10
-#define JH71XX_PMU_SW_ENCOURAGE                0x44
-#define JH71XX_PMU_TIMER_INT_MASK      0x48
-#define JH71XX_PMU_CURR_POWER_MODE     0x80
-#define JH71XX_PMU_EVENT_STATUS                0x88
-#define JH71XX_PMU_INT_STATUS          0x8C
-
-/* sw encourage cfg */
-#define JH71XX_PMU_SW_ENCOURAGE_EN_LO  0x05
-#define JH71XX_PMU_SW_ENCOURAGE_EN_HI  0x50
-#define JH71XX_PMU_SW_ENCOURAGE_DIS_LO 0x0A
-#define JH71XX_PMU_SW_ENCOURAGE_DIS_HI 0xA0
-#define JH71XX_PMU_SW_ENCOURAGE_ON     0xFF
-
-/* pmu int status */
-#define JH71XX_PMU_INT_SEQ_DONE                BIT(0)
-#define JH71XX_PMU_INT_HW_REQ          BIT(1)
-#define JH71XX_PMU_INT_SW_FAIL         GENMASK(3, 2)
-#define JH71XX_PMU_INT_HW_FAIL         GENMASK(5, 4)
-#define JH71XX_PMU_INT_PCH_FAIL                GENMASK(8, 6)
-#define JH71XX_PMU_INT_ALL_MASK                GENMASK(8, 0)
-
-/*
- * The time required for switching power status is based on the time
- * to turn on the largest domain's power, which is at microsecond level
- */
-#define JH71XX_PMU_TIMEOUT_US          100
-
-struct jh71xx_domain_info {
-       const char * const name;
-       unsigned int flags;
-       u8 bit;
-};
-
-struct jh71xx_pmu_match_data {
-       const struct jh71xx_domain_info *domain_info;
-       int num_domains;
-};
-
-struct jh71xx_pmu {
-       struct device *dev;
-       const struct jh71xx_pmu_match_data *match_data;
-       void __iomem *base;
-       struct generic_pm_domain **genpd;
-       struct genpd_onecell_data genpd_data;
-       int irq;
-       spinlock_t lock;        /* protects pmu reg */
-};
-
-struct jh71xx_pmu_dev {
-       const struct jh71xx_domain_info *domain_info;
-       struct jh71xx_pmu *pmu;
-       struct generic_pm_domain genpd;
-};
-
-static int jh71xx_pmu_get_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool *is_on)
-{
-       struct jh71xx_pmu *pmu = pmd->pmu;
-
-       if (!mask)
-               return -EINVAL;
-
-       *is_on = readl(pmu->base + JH71XX_PMU_CURR_POWER_MODE) & mask;
-
-       return 0;
-}
-
-static int jh71xx_pmu_set_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool on)
-{
-       struct jh71xx_pmu *pmu = pmd->pmu;
-       unsigned long flags;
-       u32 val;
-       u32 mode;
-       u32 encourage_lo;
-       u32 encourage_hi;
-       bool is_on;
-       int ret;
-
-       ret = jh71xx_pmu_get_state(pmd, mask, &is_on);
-       if (ret) {
-               dev_dbg(pmu->dev, "unable to get current state for %s\n",
-                       pmd->genpd.name);
-               return ret;
-       }
-
-       if (is_on == on) {
-               dev_dbg(pmu->dev, "pm domain [%s] is already %sable status.\n",
-                       pmd->genpd.name, on ? "en" : "dis");
-               return 0;
-       }
-
-       spin_lock_irqsave(&pmu->lock, flags);
-
-       /*
-        * The PMU accepts software encourage to switch power mode in the following 2 steps:
-        *
-        * 1.Configure the register SW_TURN_ON_POWER (offset 0x0c) by writing 1 to
-        *   the bit corresponding to the power domain that will be turned on
-        *   and writing 0 to the others.
-        *   Likewise, configure the register SW_TURN_OFF_POWER (offset 0x10) by
-        *   writing 1 to the bit corresponding to the power domain that will be
-        *   turned off and writing 0 to the others.
-        */
-       if (on) {
-               mode = JH71XX_PMU_SW_TURN_ON_POWER;
-               encourage_lo = JH71XX_PMU_SW_ENCOURAGE_EN_LO;
-               encourage_hi = JH71XX_PMU_SW_ENCOURAGE_EN_HI;
-       } else {
-               mode = JH71XX_PMU_SW_TURN_OFF_POWER;
-               encourage_lo = JH71XX_PMU_SW_ENCOURAGE_DIS_LO;
-               encourage_hi = JH71XX_PMU_SW_ENCOURAGE_DIS_HI;
-       }
-
-       writel(mask, pmu->base + mode);
-
-       /*
-        * 2.Write SW encourage command sequence to the Software Encourage Reg (offset 0x44)
-        *   First write SW_MODE_ENCOURAGE_ON to JH71XX_PMU_SW_ENCOURAGE. This will reset
-        *   the state machine which parses the command sequence. This register must be
-        *   written every time software wants to power on/off a domain.
-        *   Then write the lower bits of the command sequence, followed by the upper
-        *   bits. The sequence differs between powering on & off a domain.
-        */
-       writel(JH71XX_PMU_SW_ENCOURAGE_ON, pmu->base + JH71XX_PMU_SW_ENCOURAGE);
-       writel(encourage_lo, pmu->base + JH71XX_PMU_SW_ENCOURAGE);
-       writel(encourage_hi, pmu->base + JH71XX_PMU_SW_ENCOURAGE);
-
-       spin_unlock_irqrestore(&pmu->lock, flags);
-
-       /* Wait for the power domain bit to be enabled / disabled */
-       if (on) {
-               ret = readl_poll_timeout_atomic(pmu->base + JH71XX_PMU_CURR_POWER_MODE,
-                                               val, val & mask,
-                                               1, JH71XX_PMU_TIMEOUT_US);
-       } else {
-               ret = readl_poll_timeout_atomic(pmu->base + JH71XX_PMU_CURR_POWER_MODE,
-                                               val, !(val & mask),
-                                               1, JH71XX_PMU_TIMEOUT_US);
-       }
-
-       if (ret) {
-               dev_err(pmu->dev, "%s: failed to power %s\n",
-                       pmd->genpd.name, on ? "on" : "off");
-               return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
-static int jh71xx_pmu_on(struct generic_pm_domain *genpd)
-{
-       struct jh71xx_pmu_dev *pmd = container_of(genpd,
-                                                 struct jh71xx_pmu_dev, genpd);
-       u32 pwr_mask = BIT(pmd->domain_info->bit);
-
-       return jh71xx_pmu_set_state(pmd, pwr_mask, true);
-}
-
-static int jh71xx_pmu_off(struct generic_pm_domain *genpd)
-{
-       struct jh71xx_pmu_dev *pmd = container_of(genpd,
-                                                 struct jh71xx_pmu_dev, genpd);
-       u32 pwr_mask = BIT(pmd->domain_info->bit);
-
-       return jh71xx_pmu_set_state(pmd, pwr_mask, false);
-}
-
-static void jh71xx_pmu_int_enable(struct jh71xx_pmu *pmu, u32 mask, bool enable)
-{
-       u32 val;
-       unsigned long flags;
-
-       spin_lock_irqsave(&pmu->lock, flags);
-       val = readl(pmu->base + JH71XX_PMU_TIMER_INT_MASK);
-
-       if (enable)
-               val &= ~mask;
-       else
-               val |= mask;
-
-       writel(val, pmu->base + JH71XX_PMU_TIMER_INT_MASK);
-       spin_unlock_irqrestore(&pmu->lock, flags);
-}
-
-static irqreturn_t jh71xx_pmu_interrupt(int irq, void *data)
-{
-       struct jh71xx_pmu *pmu = data;
-       u32 val;
-
-       val = readl(pmu->base + JH71XX_PMU_INT_STATUS);
-
-       if (val & JH71XX_PMU_INT_SEQ_DONE)
-               dev_dbg(pmu->dev, "sequence done.\n");
-       if (val & JH71XX_PMU_INT_HW_REQ)
-               dev_dbg(pmu->dev, "hardware encourage requestion.\n");
-       if (val & JH71XX_PMU_INT_SW_FAIL)
-               dev_err(pmu->dev, "software encourage fail.\n");
-       if (val & JH71XX_PMU_INT_HW_FAIL)
-               dev_err(pmu->dev, "hardware encourage fail.\n");
-       if (val & JH71XX_PMU_INT_PCH_FAIL)
-               dev_err(pmu->dev, "p-channel fail event.\n");
-
-       /* clear interrupts */
-       writel(val, pmu->base + JH71XX_PMU_INT_STATUS);
-       writel(val, pmu->base + JH71XX_PMU_EVENT_STATUS);
-
-       return IRQ_HANDLED;
-}
-
-static int jh71xx_pmu_init_domain(struct jh71xx_pmu *pmu, int index)
-{
-       struct jh71xx_pmu_dev *pmd;
-       u32 pwr_mask;
-       int ret;
-       bool is_on = false;
-
-       pmd = devm_kzalloc(pmu->dev, sizeof(*pmd), GFP_KERNEL);
-       if (!pmd)
-               return -ENOMEM;
-
-       pmd->domain_info = &pmu->match_data->domain_info[index];
-       pmd->pmu = pmu;
-       pwr_mask = BIT(pmd->domain_info->bit);
-
-       pmd->genpd.name = pmd->domain_info->name;
-       pmd->genpd.flags = pmd->domain_info->flags;
-
-       ret = jh71xx_pmu_get_state(pmd, pwr_mask, &is_on);
-       if (ret)
-               dev_warn(pmu->dev, "unable to get current state for %s\n",
-                        pmd->genpd.name);
-
-       pmd->genpd.power_on = jh71xx_pmu_on;
-       pmd->genpd.power_off = jh71xx_pmu_off;
-       pm_genpd_init(&pmd->genpd, NULL, !is_on);
-
-       pmu->genpd_data.domains[index] = &pmd->genpd;
-
-       return 0;
-}
-
-static int jh71xx_pmu_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       const struct jh71xx_pmu_match_data *match_data;
-       struct jh71xx_pmu *pmu;
-       unsigned int i;
-       int ret;
-
-       pmu = devm_kzalloc(dev, sizeof(*pmu), GFP_KERNEL);
-       if (!pmu)
-               return -ENOMEM;
-
-       pmu->base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(pmu->base))
-               return PTR_ERR(pmu->base);
-
-       pmu->irq = platform_get_irq(pdev, 0);
-       if (pmu->irq < 0)
-               return pmu->irq;
-
-       ret = devm_request_irq(dev, pmu->irq, jh71xx_pmu_interrupt,
-                              0, pdev->name, pmu);
-       if (ret)
-               dev_err(dev, "failed to request irq\n");
-
-       match_data = of_device_get_match_data(dev);
-       if (!match_data)
-               return -EINVAL;
-
-       pmu->genpd = devm_kcalloc(dev, match_data->num_domains,
-                                 sizeof(struct generic_pm_domain *),
-                                 GFP_KERNEL);
-       if (!pmu->genpd)
-               return -ENOMEM;
-
-       pmu->dev = dev;
-       pmu->match_data = match_data;
-       pmu->genpd_data.domains = pmu->genpd;
-       pmu->genpd_data.num_domains = match_data->num_domains;
-
-       for (i = 0; i < match_data->num_domains; i++) {
-               ret = jh71xx_pmu_init_domain(pmu, i);
-               if (ret) {
-                       dev_err(dev, "failed to initialize power domain\n");
-                       return ret;
-               }
-       }
-
-       spin_lock_init(&pmu->lock);
-       jh71xx_pmu_int_enable(pmu, JH71XX_PMU_INT_ALL_MASK & ~JH71XX_PMU_INT_PCH_FAIL, true);
-
-       ret = of_genpd_add_provider_onecell(np, &pmu->genpd_data);
-       if (ret) {
-               dev_err(dev, "failed to register genpd driver: %d\n", ret);
-               return ret;
-       }
-
-       dev_dbg(dev, "registered %u power domains\n", i);
-
-       return 0;
-}
-
-static const struct jh71xx_domain_info jh7110_power_domains[] = {
-       [JH7110_PD_SYSTOP] = {
-               .name = "SYSTOP",
-               .bit = 0,
-               .flags = GENPD_FLAG_ALWAYS_ON,
-       },
-       [JH7110_PD_CPU] = {
-               .name = "CPU",
-               .bit = 1,
-               .flags = GENPD_FLAG_ALWAYS_ON,
-       },
-       [JH7110_PD_GPUA] = {
-               .name = "GPUA",
-               .bit = 2,
-       },
-       [JH7110_PD_VDEC] = {
-               .name = "VDEC",
-               .bit = 3,
-       },
-       [JH7110_PD_VOUT] = {
-               .name = "VOUT",
-               .bit = 4,
-       },
-       [JH7110_PD_ISP] = {
-               .name = "ISP",
-               .bit = 5,
-       },
-       [JH7110_PD_VENC] = {
-               .name = "VENC",
-               .bit = 6,
-       },
-};
-
-static const struct jh71xx_pmu_match_data jh7110_pmu = {
-       .num_domains = ARRAY_SIZE(jh7110_power_domains),
-       .domain_info = jh7110_power_domains,
-};
-
-static const struct of_device_id jh71xx_pmu_of_match[] = {
-       {
-               .compatible = "starfive,jh7110-pmu",
-               .data = (void *)&jh7110_pmu,
-       }, {
-               /* sentinel */
-       }
-};
-
-static struct platform_driver jh71xx_pmu_driver = {
-       .probe = jh71xx_pmu_probe,
-       .driver = {
-               .name = "jh71xx-pmu",
-               .of_match_table = jh71xx_pmu_of_match,
-               .suppress_bind_attrs = true,
-       },
-};
-builtin_platform_driver(jh71xx_pmu_driver);
-
-MODULE_AUTHOR("Walker Chen <walker.chen@starfivetech.com>");
-MODULE_DESCRIPTION("StarFive JH71XX PMU Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/genpd/sunxi/Makefile b/drivers/genpd/sunxi/Makefile
deleted file mode 100644 (file)
index ec1d7a2..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_SUN20I_PPU)               += sun20i-ppu.o
diff --git a/drivers/genpd/sunxi/sun20i-ppu.c b/drivers/genpd/sunxi/sun20i-ppu.c
deleted file mode 100644 (file)
index 8700f9d..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-
-#include <linux/bitfield.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/reset.h>
-
-#define PD_STATE_ON                    1
-#define PD_STATE_OFF                   2
-
-#define PD_RSTN_REG                    0x00
-#define PD_CLK_GATE_REG                        0x04
-#define PD_PWROFF_GATE_REG             0x08
-#define PD_PSW_ON_REG                  0x0c
-#define PD_PSW_OFF_REG                 0x10
-#define PD_PSW_DELAY_REG               0x14
-#define PD_OFF_DELAY_REG               0x18
-#define PD_ON_DELAY_REG                        0x1c
-#define PD_COMMAND_REG                 0x20
-#define PD_STATUS_REG                  0x24
-#define PD_STATUS_COMPLETE                     BIT(1)
-#define PD_STATUS_BUSY                         BIT(3)
-#define PD_STATUS_STATE                                GENMASK(17, 16)
-#define PD_ACTIVE_CTRL_REG             0x2c
-#define PD_GATE_STATUS_REG             0x30
-#define PD_RSTN_STATUS                         BIT(0)
-#define PD_CLK_GATE_STATUS                     BIT(1)
-#define PD_PWROFF_GATE_STATUS                  BIT(2)
-#define PD_PSW_STATUS_REG              0x34
-
-#define PD_REGS_SIZE                   0x80
-
-struct sun20i_ppu_desc {
-       const char *const               *names;
-       unsigned int                    num_domains;
-};
-
-struct sun20i_ppu_pd {
-       struct generic_pm_domain        genpd;
-       void __iomem                    *base;
-};
-
-#define to_sun20i_ppu_pd(_genpd) \
-       container_of(_genpd, struct sun20i_ppu_pd, genpd)
-
-static bool sun20i_ppu_pd_is_on(const struct sun20i_ppu_pd *pd)
-{
-       u32 status = readl(pd->base + PD_STATUS_REG);
-
-       return FIELD_GET(PD_STATUS_STATE, status) == PD_STATE_ON;
-}
-
-static int sun20i_ppu_pd_set_power(const struct sun20i_ppu_pd *pd, bool power_on)
-{
-       u32 state, status;
-       int ret;
-
-       if (sun20i_ppu_pd_is_on(pd) == power_on)
-               return 0;
-
-       /* Wait for the power controller to be idle. */
-       ret = readl_poll_timeout(pd->base + PD_STATUS_REG, status,
-                                !(status & PD_STATUS_BUSY), 100, 1000);
-       if (ret)
-               return ret;
-
-       state = power_on ? PD_STATE_ON : PD_STATE_OFF;
-       writel(state, pd->base + PD_COMMAND_REG);
-
-       /* Wait for the state transition to complete. */
-       ret = readl_poll_timeout(pd->base + PD_STATUS_REG, status,
-                                FIELD_GET(PD_STATUS_STATE, status) == state &&
-                                (status & PD_STATUS_COMPLETE), 100, 1000);
-       if (ret)
-               return ret;
-
-       /* Clear the completion flag. */
-       writel(status, pd->base + PD_STATUS_REG);
-
-       return 0;
-}
-
-static int sun20i_ppu_pd_power_on(struct generic_pm_domain *genpd)
-{
-       const struct sun20i_ppu_pd *pd = to_sun20i_ppu_pd(genpd);
-
-       return sun20i_ppu_pd_set_power(pd, true);
-}
-
-static int sun20i_ppu_pd_power_off(struct generic_pm_domain *genpd)
-{
-       const struct sun20i_ppu_pd *pd = to_sun20i_ppu_pd(genpd);
-
-       return sun20i_ppu_pd_set_power(pd, false);
-}
-
-static int sun20i_ppu_probe(struct platform_device *pdev)
-{
-       const struct sun20i_ppu_desc *desc;
-       struct device *dev = &pdev->dev;
-       struct genpd_onecell_data *ppu;
-       struct sun20i_ppu_pd *pds;
-       struct reset_control *rst;
-       void __iomem *base;
-       struct clk *clk;
-       int ret;
-
-       desc = of_device_get_match_data(dev);
-       if (!desc)
-               return -EINVAL;
-
-       pds = devm_kcalloc(dev, desc->num_domains, sizeof(*pds), GFP_KERNEL);
-       if (!pds)
-               return -ENOMEM;
-
-       ppu = devm_kzalloc(dev, sizeof(*ppu), GFP_KERNEL);
-       if (!ppu)
-               return -ENOMEM;
-
-       ppu->domains = devm_kcalloc(dev, desc->num_domains,
-                                   sizeof(*ppu->domains), GFP_KERNEL);
-       if (!ppu->domains)
-               return -ENOMEM;
-
-       ppu->num_domains = desc->num_domains;
-       platform_set_drvdata(pdev, ppu);
-
-       base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       clk = devm_clk_get_enabled(dev, NULL);
-       if (IS_ERR(clk))
-               return PTR_ERR(clk);
-
-       rst = devm_reset_control_get_exclusive(dev, NULL);
-       if (IS_ERR(rst))
-               return PTR_ERR(rst);
-
-       ret = reset_control_deassert(rst);
-       if (ret)
-               return ret;
-
-       for (unsigned int i = 0; i < ppu->num_domains; ++i) {
-               struct sun20i_ppu_pd *pd = &pds[i];
-
-               pd->genpd.name          = desc->names[i];
-               pd->genpd.power_off     = sun20i_ppu_pd_power_off;
-               pd->genpd.power_on      = sun20i_ppu_pd_power_on;
-               pd->base                = base + PD_REGS_SIZE * i;
-
-               ret = pm_genpd_init(&pd->genpd, NULL, sun20i_ppu_pd_is_on(pd));
-               if (ret) {
-                       dev_warn(dev, "Failed to add '%s' domain: %d\n",
-                                pd->genpd.name, ret);
-                       continue;
-               }
-
-               ppu->domains[i] = &pd->genpd;
-       }
-
-       ret = of_genpd_add_provider_onecell(dev->of_node, ppu);
-       if (ret)
-               dev_warn(dev, "Failed to add provider: %d\n", ret);
-
-       return 0;
-}
-
-static const char *const sun20i_d1_ppu_pd_names[] = {
-       "CPU",
-       "VE",
-       "DSP",
-};
-
-static const struct sun20i_ppu_desc sun20i_d1_ppu_desc = {
-       .names          = sun20i_d1_ppu_pd_names,
-       .num_domains    = ARRAY_SIZE(sun20i_d1_ppu_pd_names),
-};
-
-static const struct of_device_id sun20i_ppu_of_match[] = {
-       {
-               .compatible     = "allwinner,sun20i-d1-ppu",
-               .data           = &sun20i_d1_ppu_desc,
-       },
-       { }
-};
-MODULE_DEVICE_TABLE(of, sun20i_ppu_of_match);
-
-static struct platform_driver sun20i_ppu_driver = {
-       .probe  = sun20i_ppu_probe,
-       .driver = {
-               .name                   = "sun20i-ppu",
-               .of_match_table         = sun20i_ppu_of_match,
-               /* Power domains cannot be removed while they are in use. */
-               .suppress_bind_attrs    = true,
-       },
-};
-module_platform_driver(sun20i_ppu_driver);
-
-MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
-MODULE_DESCRIPTION("Allwinner D1 PPU power domain driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/genpd/tegra/Makefile b/drivers/genpd/tegra/Makefile
deleted file mode 100644 (file)
index ec8acfd..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_SOC_TEGRA_POWERGATE_BPMP) += powergate-bpmp.o
diff --git a/drivers/genpd/tegra/powergate-bpmp.c b/drivers/genpd/tegra/powergate-bpmp.c
deleted file mode 100644 (file)
index 179ed89..0000000
+++ /dev/null
@@ -1,361 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved
- */
-
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/slab.h>
-
-#include <soc/tegra/bpmp.h>
-#include <soc/tegra/bpmp-abi.h>
-
-struct tegra_powergate_info {
-       unsigned int id;
-       char *name;
-};
-
-struct tegra_powergate {
-       struct generic_pm_domain genpd;
-       struct tegra_bpmp *bpmp;
-       unsigned int id;
-};
-
-static inline struct tegra_powergate *
-to_tegra_powergate(struct generic_pm_domain *genpd)
-{
-       return container_of(genpd, struct tegra_powergate, genpd);
-}
-
-static int tegra_bpmp_powergate_set_state(struct tegra_bpmp *bpmp,
-                                         unsigned int id, u32 state)
-{
-       struct mrq_pg_request request;
-       struct tegra_bpmp_message msg;
-       int err;
-
-       memset(&request, 0, sizeof(request));
-       request.cmd = CMD_PG_SET_STATE;
-       request.id = id;
-       request.set_state.state = state;
-
-       memset(&msg, 0, sizeof(msg));
-       msg.mrq = MRQ_PG;
-       msg.tx.data = &request;
-       msg.tx.size = sizeof(request);
-
-       err = tegra_bpmp_transfer(bpmp, &msg);
-       if (err < 0)
-               return err;
-       else if (msg.rx.ret < 0)
-               return -EINVAL;
-
-       return 0;
-}
-
-static int tegra_bpmp_powergate_get_state(struct tegra_bpmp *bpmp,
-                                         unsigned int id)
-{
-       struct mrq_pg_response response;
-       struct mrq_pg_request request;
-       struct tegra_bpmp_message msg;
-       int err;
-
-       memset(&request, 0, sizeof(request));
-       request.cmd = CMD_PG_GET_STATE;
-       request.id = id;
-
-       memset(&response, 0, sizeof(response));
-
-       memset(&msg, 0, sizeof(msg));
-       msg.mrq = MRQ_PG;
-       msg.tx.data = &request;
-       msg.tx.size = sizeof(request);
-       msg.rx.data = &response;
-       msg.rx.size = sizeof(response);
-
-       err = tegra_bpmp_transfer(bpmp, &msg);
-       if (err < 0)
-               return PG_STATE_OFF;
-       else if (msg.rx.ret < 0)
-               return -EINVAL;
-
-       return response.get_state.state;
-}
-
-static int tegra_bpmp_powergate_get_max_id(struct tegra_bpmp *bpmp)
-{
-       struct mrq_pg_response response;
-       struct mrq_pg_request request;
-       struct tegra_bpmp_message msg;
-       int err;
-
-       memset(&request, 0, sizeof(request));
-       request.cmd = CMD_PG_GET_MAX_ID;
-
-       memset(&response, 0, sizeof(response));
-
-       memset(&msg, 0, sizeof(msg));
-       msg.mrq = MRQ_PG;
-       msg.tx.data = &request;
-       msg.tx.size = sizeof(request);
-       msg.rx.data = &response;
-       msg.rx.size = sizeof(response);
-
-       err = tegra_bpmp_transfer(bpmp, &msg);
-       if (err < 0)
-               return err;
-       else if (msg.rx.ret < 0)
-               return -EINVAL;
-
-       return response.get_max_id.max_id;
-}
-
-static char *tegra_bpmp_powergate_get_name(struct tegra_bpmp *bpmp,
-                                          unsigned int id)
-{
-       struct mrq_pg_response response;
-       struct mrq_pg_request request;
-       struct tegra_bpmp_message msg;
-       int err;
-
-       memset(&request, 0, sizeof(request));
-       request.cmd = CMD_PG_GET_NAME;
-       request.id = id;
-
-       memset(&response, 0, sizeof(response));
-
-       memset(&msg, 0, sizeof(msg));
-       msg.mrq = MRQ_PG;
-       msg.tx.data = &request;
-       msg.tx.size = sizeof(request);
-       msg.rx.data = &response;
-       msg.rx.size = sizeof(response);
-
-       err = tegra_bpmp_transfer(bpmp, &msg);
-       if (err < 0 || msg.rx.ret < 0)
-               return NULL;
-
-       return kstrdup(response.get_name.name, GFP_KERNEL);
-}
-
-static inline bool tegra_bpmp_powergate_is_powered(struct tegra_bpmp *bpmp,
-                                                  unsigned int id)
-{
-       return tegra_bpmp_powergate_get_state(bpmp, id) != PG_STATE_OFF;
-}
-
-static int tegra_powergate_power_on(struct generic_pm_domain *domain)
-{
-       struct tegra_powergate *powergate = to_tegra_powergate(domain);
-       struct tegra_bpmp *bpmp = powergate->bpmp;
-
-       return tegra_bpmp_powergate_set_state(bpmp, powergate->id,
-                                             PG_STATE_ON);
-}
-
-static int tegra_powergate_power_off(struct generic_pm_domain *domain)
-{
-       struct tegra_powergate *powergate = to_tegra_powergate(domain);
-       struct tegra_bpmp *bpmp = powergate->bpmp;
-
-       return tegra_bpmp_powergate_set_state(bpmp, powergate->id,
-                                             PG_STATE_OFF);
-}
-
-static struct tegra_powergate *
-tegra_powergate_add(struct tegra_bpmp *bpmp,
-                   const struct tegra_powergate_info *info)
-{
-       struct tegra_powergate *powergate;
-       bool off;
-       int err;
-
-       off = !tegra_bpmp_powergate_is_powered(bpmp, info->id);
-
-       powergate = devm_kzalloc(bpmp->dev, sizeof(*powergate), GFP_KERNEL);
-       if (!powergate)
-               return ERR_PTR(-ENOMEM);
-
-       powergate->id = info->id;
-       powergate->bpmp = bpmp;
-
-       powergate->genpd.name = kstrdup(info->name, GFP_KERNEL);
-       powergate->genpd.power_on = tegra_powergate_power_on;
-       powergate->genpd.power_off = tegra_powergate_power_off;
-
-       err = pm_genpd_init(&powergate->genpd, NULL, off);
-       if (err < 0) {
-               kfree(powergate->genpd.name);
-               return ERR_PTR(err);
-       }
-
-       return powergate;
-}
-
-static void tegra_powergate_remove(struct tegra_powergate *powergate)
-{
-       struct generic_pm_domain *genpd = &powergate->genpd;
-       struct tegra_bpmp *bpmp = powergate->bpmp;
-       int err;
-
-       err = pm_genpd_remove(genpd);
-       if (err < 0)
-               dev_err(bpmp->dev, "failed to remove power domain %s: %d\n",
-                       genpd->name, err);
-
-       kfree(genpd->name);
-}
-
-static int
-tegra_bpmp_probe_powergates(struct tegra_bpmp *bpmp,
-                           struct tegra_powergate_info **powergatesp)
-{
-       struct tegra_powergate_info *powergates;
-       unsigned int max_id, id, count = 0;
-       unsigned int num_holes = 0;
-       int err;
-
-       err = tegra_bpmp_powergate_get_max_id(bpmp);
-       if (err < 0)
-               return err;
-
-       max_id = err;
-
-       dev_dbg(bpmp->dev, "maximum powergate ID: %u\n", max_id);
-
-       powergates = kcalloc(max_id + 1, sizeof(*powergates), GFP_KERNEL);
-       if (!powergates)
-               return -ENOMEM;
-
-       for (id = 0; id <= max_id; id++) {
-               struct tegra_powergate_info *info = &powergates[count];
-
-               info->name = tegra_bpmp_powergate_get_name(bpmp, id);
-               if (!info->name || info->name[0] == '\0') {
-                       num_holes++;
-                       continue;
-               }
-
-               info->id = id;
-               count++;
-       }
-
-       dev_dbg(bpmp->dev, "holes: %u\n", num_holes);
-
-       *powergatesp = powergates;
-
-       return count;
-}
-
-static int tegra_bpmp_add_powergates(struct tegra_bpmp *bpmp,
-                                    struct tegra_powergate_info *powergates,
-                                    unsigned int count)
-{
-       struct genpd_onecell_data *genpd = &bpmp->genpd;
-       struct generic_pm_domain **domains;
-       struct tegra_powergate *powergate;
-       unsigned int i;
-       int err;
-
-       domains = kcalloc(count, sizeof(*domains), GFP_KERNEL);
-       if (!domains)
-               return -ENOMEM;
-
-       for (i = 0; i < count; i++) {
-               powergate = tegra_powergate_add(bpmp, &powergates[i]);
-               if (IS_ERR(powergate)) {
-                       err = PTR_ERR(powergate);
-                       goto remove;
-               }
-
-               dev_dbg(bpmp->dev, "added power domain %s\n",
-                       powergate->genpd.name);
-               domains[i] = &powergate->genpd;
-       }
-
-       genpd->num_domains = count;
-       genpd->domains = domains;
-
-       return 0;
-
-remove:
-       while (i--) {
-               powergate = to_tegra_powergate(domains[i]);
-               tegra_powergate_remove(powergate);
-       }
-
-       kfree(domains);
-       return err;
-}
-
-static void tegra_bpmp_remove_powergates(struct tegra_bpmp *bpmp)
-{
-       struct genpd_onecell_data *genpd = &bpmp->genpd;
-       unsigned int i = genpd->num_domains;
-       struct tegra_powergate *powergate;
-
-       while (i--) {
-               dev_dbg(bpmp->dev, "removing power domain %s\n",
-                       genpd->domains[i]->name);
-               powergate = to_tegra_powergate(genpd->domains[i]);
-               tegra_powergate_remove(powergate);
-       }
-}
-
-static struct generic_pm_domain *
-tegra_powergate_xlate(struct of_phandle_args *spec, void *data)
-{
-       struct generic_pm_domain *domain = ERR_PTR(-ENOENT);
-       struct genpd_onecell_data *genpd = data;
-       unsigned int i;
-
-       for (i = 0; i < genpd->num_domains; i++) {
-               struct tegra_powergate *powergate;
-
-               powergate = to_tegra_powergate(genpd->domains[i]);
-               if (powergate->id == spec->args[0]) {
-                       domain = &powergate->genpd;
-                       break;
-               }
-       }
-
-       return domain;
-}
-
-int tegra_bpmp_init_powergates(struct tegra_bpmp *bpmp)
-{
-       struct device_node *np = bpmp->dev->of_node;
-       struct tegra_powergate_info *powergates;
-       struct device *dev = bpmp->dev;
-       unsigned int count, i;
-       int err;
-
-       err = tegra_bpmp_probe_powergates(bpmp, &powergates);
-       if (err < 0)
-               return err;
-
-       count = err;
-
-       dev_dbg(dev, "%u power domains probed\n", count);
-
-       err = tegra_bpmp_add_powergates(bpmp, powergates, count);
-       if (err < 0)
-               goto free;
-
-       bpmp->genpd.xlate = tegra_powergate_xlate;
-
-       err = of_genpd_add_provider_onecell(np, &bpmp->genpd);
-       if (err < 0) {
-               dev_err(dev, "failed to add power domain provider: %d\n", err);
-               tegra_bpmp_remove_powergates(bpmp);
-       }
-
-free:
-       for (i = 0; i < count; i++)
-               kfree(powergates[i].name);
-
-       kfree(powergates);
-       return err;
-}
diff --git a/drivers/genpd/ti/Makefile b/drivers/genpd/ti/Makefile
deleted file mode 100644 (file)
index 69580af..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_ARCH_OMAP2PLUS)           += omap_prm.o
-obj-$(CONFIG_TI_SCI_PM_DOMAINS)                += ti_sci_pm_domains.o
diff --git a/drivers/genpd/ti/omap_prm.c b/drivers/genpd/ti/omap_prm.c
deleted file mode 100644 (file)
index c2feae3..0000000
+++ /dev/null
@@ -1,989 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * OMAP2+ PRM driver
- *
- * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
- *     Tero Kristo <t-kristo@ti.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_clock.h>
-#include <linux/pm_domain.h>
-#include <linux/reset-controller.h>
-#include <linux/delay.h>
-
-#include <linux/platform_data/ti-prm.h>
-
-enum omap_prm_domain_mode {
-       OMAP_PRMD_OFF,
-       OMAP_PRMD_RETENTION,
-       OMAP_PRMD_ON_INACTIVE,
-       OMAP_PRMD_ON_ACTIVE,
-};
-
-struct omap_prm_domain_map {
-       unsigned int usable_modes;      /* Mask of hardware supported modes */
-       unsigned long statechange:1;    /* Optional low-power state change */
-       unsigned long logicretstate:1;  /* Optional logic off mode */
-};
-
-struct omap_prm_domain {
-       struct device *dev;
-       struct omap_prm *prm;
-       struct generic_pm_domain pd;
-       u16 pwrstctrl;
-       u16 pwrstst;
-       const struct omap_prm_domain_map *cap;
-       u32 pwrstctrl_saved;
-       unsigned int uses_pm_clk:1;
-};
-
-struct omap_rst_map {
-       s8 rst;
-       s8 st;
-};
-
-struct omap_prm_data {
-       u32 base;
-       const char *name;
-       const char *clkdm_name;
-       u16 pwrstctrl;
-       u16 pwrstst;
-       const struct omap_prm_domain_map *dmap;
-       u16 rstctrl;
-       u16 rstst;
-       const struct omap_rst_map *rstmap;
-       u8 flags;
-};
-
-struct omap_prm {
-       const struct omap_prm_data *data;
-       void __iomem *base;
-       struct omap_prm_domain *prmd;
-};
-
-struct omap_reset_data {
-       struct reset_controller_dev rcdev;
-       struct omap_prm *prm;
-       u32 mask;
-       spinlock_t lock;
-       struct clockdomain *clkdm;
-       struct device *dev;
-};
-
-#define genpd_to_prm_domain(gpd) container_of(gpd, struct omap_prm_domain, pd)
-#define to_omap_reset_data(p) container_of((p), struct omap_reset_data, rcdev)
-
-#define OMAP_MAX_RESETS                8
-#define OMAP_RESET_MAX_WAIT    10000
-
-#define OMAP_PRM_HAS_RSTCTRL   BIT(0)
-#define OMAP_PRM_HAS_RSTST     BIT(1)
-#define OMAP_PRM_HAS_NO_CLKDM  BIT(2)
-#define OMAP_PRM_RET_WHEN_IDLE BIT(3)
-
-#define OMAP_PRM_HAS_RESETS    (OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_RSTST)
-
-#define PRM_STATE_MAX_WAIT     10000
-#define PRM_LOGICRETSTATE      BIT(2)
-#define PRM_LOWPOWERSTATECHANGE        BIT(4)
-#define PRM_POWERSTATE_MASK    OMAP_PRMD_ON_ACTIVE
-
-#define PRM_ST_INTRANSITION    BIT(20)
-
-static const struct omap_prm_domain_map omap_prm_all = {
-       .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_ON_INACTIVE) |
-                       BIT(OMAP_PRMD_RETENTION) | BIT(OMAP_PRMD_OFF),
-       .statechange = 1,
-       .logicretstate = 1,
-};
-
-static const struct omap_prm_domain_map omap_prm_noinact = {
-       .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_RETENTION) |
-                       BIT(OMAP_PRMD_OFF),
-       .statechange = 1,
-       .logicretstate = 1,
-};
-
-static const struct omap_prm_domain_map omap_prm_nooff = {
-       .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_ON_INACTIVE) |
-                       BIT(OMAP_PRMD_RETENTION),
-       .statechange = 1,
-       .logicretstate = 1,
-};
-
-static const struct omap_prm_domain_map omap_prm_onoff_noauto = {
-       .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_OFF),
-       .statechange = 1,
-};
-
-static const struct omap_prm_domain_map omap_prm_alwon = {
-       .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE),
-};
-
-static const struct omap_prm_domain_map omap_prm_reton = {
-       .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_RETENTION),
-       .statechange = 1,
-       .logicretstate = 1,
-};
-
-static const struct omap_rst_map rst_map_0[] = {
-       { .rst = 0, .st = 0 },
-       { .rst = -1 },
-};
-
-static const struct omap_rst_map rst_map_01[] = {
-       { .rst = 0, .st = 0 },
-       { .rst = 1, .st = 1 },
-       { .rst = -1 },
-};
-
-static const struct omap_rst_map rst_map_012[] = {
-       { .rst = 0, .st = 0 },
-       { .rst = 1, .st = 1 },
-       { .rst = 2, .st = 2 },
-       { .rst = -1 },
-};
-
-static const struct omap_prm_data omap4_prm_data[] = {
-       {
-               .name = "mpu", .base = 0x4a306300,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
-       },
-       {
-               .name = "tesla", .base = 0x4a306400,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
-               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
-       },
-       {
-               .name = "abe", .base = 0x4a306500,
-               .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_all,
-       },
-       {
-               .name = "always_on_core", .base = 0x4a306600,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
-       },
-       {
-               .name = "core", .base = 0x4a306700,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
-               .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ducati",
-               .rstmap = rst_map_012,
-               .flags = OMAP_PRM_RET_WHEN_IDLE,
-       },
-       {
-               .name = "ivahd", .base = 0x4a306f00,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
-               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012
-       },
-       {
-               .name = "cam", .base = 0x4a307000,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-       },
-       {
-               .name = "dss", .base = 0x4a307100,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact
-       },
-       {
-               .name = "gfx", .base = 0x4a307200,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
-       },
-       {
-               .name = "l3init", .base = 0x4a307300,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton
-       },
-       {
-               .name = "l4per", .base = 0x4a307400,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
-               .flags = OMAP_PRM_RET_WHEN_IDLE,
-       },
-       {
-               .name = "cefuse", .base = 0x4a307600,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
-       },
-       {
-               .name = "wkup", .base = 0x4a307700,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon
-       },
-       {
-               .name = "emu", .base = 0x4a307900,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
-       },
-       {
-               .name = "device", .base = 0x4a307b00,
-               .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01,
-               .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
-       },
-       { },
-};
-
-static const struct omap_prm_data omap5_prm_data[] = {
-       {
-               .name = "mpu", .base = 0x4ae06300,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
-       },
-       {
-               .name = "dsp", .base = 0x4ae06400,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
-               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
-       },
-       {
-               .name = "abe", .base = 0x4ae06500,
-               .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_nooff,
-       },
-       {
-               .name = "coreaon", .base = 0x4ae06600,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon
-       },
-       {
-               .name = "core", .base = 0x4ae06700,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
-               .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ipu",
-               .rstmap = rst_map_012
-       },
-       {
-               .name = "iva", .base = 0x4ae07200,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
-               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012
-       },
-       {
-               .name = "cam", .base = 0x4ae07300,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
-       },
-       {
-               .name = "dss", .base = 0x4ae07400,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact
-       },
-       {
-               .name = "gpu", .base = 0x4ae07500,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
-       },
-       {
-               .name = "l3init", .base = 0x4ae07600,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton
-       },
-       {
-               .name = "custefuse", .base = 0x4ae07700,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
-       },
-       {
-               .name = "wkupaon", .base = 0x4ae07800,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon
-       },
-       {
-               .name = "emu", .base = 0x4ae07a00,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
-       },
-       {
-               .name = "device", .base = 0x4ae07c00,
-               .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01,
-               .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
-       },
-       { },
-};
-
-static const struct omap_prm_data dra7_prm_data[] = {
-       {
-               .name = "mpu", .base = 0x4ae06300,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
-       },
-       {
-               .name = "dsp1", .base = 0x4ae06400,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01,
-       },
-       {
-               .name = "ipu", .base = 0x4ae06500,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012,
-               .clkdm_name = "ipu1"
-       },
-       {
-               .name = "coreaon", .base = 0x4ae06628,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
-       },
-       {
-               .name = "core", .base = 0x4ae06700,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
-               .rstctrl = 0x210, .rstst = 0x214, .rstmap = rst_map_012,
-               .clkdm_name = "ipu2"
-       },
-       {
-               .name = "iva", .base = 0x4ae06f00,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012,
-       },
-       {
-               .name = "cam", .base = 0x4ae07000,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-       },
-       {
-               .name = "dss", .base = 0x4ae07100,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-       },
-       {
-               .name = "gpu", .base = 0x4ae07200,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-       },
-       {
-               .name = "l3init", .base = 0x4ae07300,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
-               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01,
-               .clkdm_name = "pcie"
-       },
-       {
-               .name = "l4per", .base = 0x4ae07400,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
-       },
-       {
-               .name = "custefuse", .base = 0x4ae07600,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-       },
-       {
-               .name = "wkupaon", .base = 0x4ae07724,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
-       },
-       {
-               .name = "emu", .base = 0x4ae07900,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-       },
-       {
-               .name = "dsp2", .base = 0x4ae07b00,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
-       },
-       {
-               .name = "eve1", .base = 0x4ae07b40,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
-       },
-       {
-               .name = "eve2", .base = 0x4ae07b80,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
-       },
-       {
-               .name = "eve3", .base = 0x4ae07bc0,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
-       },
-       {
-               .name = "eve4", .base = 0x4ae07c00,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
-       },
-       {
-               .name = "rtc", .base = 0x4ae07c60,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
-       },
-       {
-               .name = "vpe", .base = 0x4ae07c80,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-       },
-       { },
-};
-
-static const struct omap_rst_map am3_per_rst_map[] = {
-       { .rst = 1 },
-       { .rst = -1 },
-};
-
-static const struct omap_rst_map am3_wkup_rst_map[] = {
-       { .rst = 3, .st = 5 },
-       { .rst = -1 },
-};
-
-static const struct omap_prm_data am3_prm_data[] = {
-       {
-               .name = "per", .base = 0x44e00c00,
-               .pwrstctrl = 0xc, .pwrstst = 0x8, .dmap = &omap_prm_noinact,
-               .rstctrl = 0x0, .rstmap = am3_per_rst_map,
-               .flags = OMAP_PRM_HAS_RSTCTRL, .clkdm_name = "pruss_ocp"
-       },
-       {
-               .name = "wkup", .base = 0x44e00d00,
-               .pwrstctrl = 0x4, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
-               .rstctrl = 0x0, .rstst = 0xc, .rstmap = am3_wkup_rst_map,
-               .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
-       },
-       {
-               .name = "mpu", .base = 0x44e00e00,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
-       },
-       {
-               .name = "device", .base = 0x44e00f00,
-               .rstctrl = 0x0, .rstst = 0x8, .rstmap = rst_map_01,
-               .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
-       },
-       {
-               .name = "rtc", .base = 0x44e01000,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
-       },
-       {
-               .name = "gfx", .base = 0x44e01100,
-               .pwrstctrl = 0, .pwrstst = 0x10, .dmap = &omap_prm_noinact,
-               .rstctrl = 0x4, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3",
-       },
-       {
-               .name = "cefuse", .base = 0x44e01200,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-       },
-       { },
-};
-
-static const struct omap_rst_map am4_per_rst_map[] = {
-       { .rst = 1, .st = 0 },
-       { .rst = -1 },
-};
-
-static const struct omap_rst_map am4_device_rst_map[] = {
-       { .rst = 0, .st = 1 },
-       { .rst = 1, .st = 0 },
-       { .rst = -1 },
-};
-
-static const struct omap_prm_data am4_prm_data[] = {
-       {
-               .name = "mpu", .base = 0x44df0300,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
-       },
-       {
-               .name = "gfx", .base = 0x44df0400,
-               .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3",
-       },
-       {
-               .name = "rtc", .base = 0x44df0500,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
-       },
-       {
-               .name = "tamper", .base = 0x44df0600,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
-       },
-       {
-               .name = "cefuse", .base = 0x44df0700,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
-       },
-       {
-               .name = "per", .base = 0x44df0800,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
-               .rstctrl = 0x10, .rstst = 0x14, .rstmap = am4_per_rst_map,
-               .clkdm_name = "pruss_ocp"
-       },
-       {
-               .name = "wkup", .base = 0x44df2000,
-               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
-               .rstctrl = 0x10, .rstst = 0x14, .rstmap = am3_wkup_rst_map,
-               .flags = OMAP_PRM_HAS_NO_CLKDM
-       },
-       {
-               .name = "device", .base = 0x44df4000,
-               .rstctrl = 0x0, .rstst = 0x4, .rstmap = am4_device_rst_map,
-               .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
-       },
-       { },
-};
-
-static const struct of_device_id omap_prm_id_table[] = {
-       { .compatible = "ti,omap4-prm-inst", .data = omap4_prm_data },
-       { .compatible = "ti,omap5-prm-inst", .data = omap5_prm_data },
-       { .compatible = "ti,dra7-prm-inst", .data = dra7_prm_data },
-       { .compatible = "ti,am3-prm-inst", .data = am3_prm_data },
-       { .compatible = "ti,am4-prm-inst", .data = am4_prm_data },
-       { },
-};
-
-#ifdef DEBUG
-static void omap_prm_domain_show_state(struct omap_prm_domain *prmd,
-                                      const char *desc)
-{
-       dev_dbg(prmd->dev, "%s %s: %08x/%08x\n",
-               prmd->pd.name, desc,
-               readl_relaxed(prmd->prm->base + prmd->pwrstctrl),
-               readl_relaxed(prmd->prm->base + prmd->pwrstst));
-}
-#else
-static inline void omap_prm_domain_show_state(struct omap_prm_domain *prmd,
-                                             const char *desc)
-{
-}
-#endif
-
-static int omap_prm_domain_power_on(struct generic_pm_domain *domain)
-{
-       struct omap_prm_domain *prmd;
-       int ret;
-       u32 v, mode;
-
-       prmd = genpd_to_prm_domain(domain);
-       if (!prmd->cap)
-               return 0;
-
-       omap_prm_domain_show_state(prmd, "on: previous state");
-
-       if (prmd->pwrstctrl_saved)
-               v = prmd->pwrstctrl_saved;
-       else
-               v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl);
-
-       if (prmd->prm->data->flags & OMAP_PRM_RET_WHEN_IDLE)
-               mode = OMAP_PRMD_RETENTION;
-       else
-               mode = OMAP_PRMD_ON_ACTIVE;
-
-       writel_relaxed((v & ~PRM_POWERSTATE_MASK) | mode,
-                      prmd->prm->base + prmd->pwrstctrl);
-
-       /* wait for the transition bit to get cleared */
-       ret = readl_relaxed_poll_timeout(prmd->prm->base + prmd->pwrstst,
-                                        v, !(v & PRM_ST_INTRANSITION), 1,
-                                        PRM_STATE_MAX_WAIT);
-       if (ret)
-               dev_err(prmd->dev, "%s: %s timed out\n",
-                       prmd->pd.name, __func__);
-
-       omap_prm_domain_show_state(prmd, "on: new state");
-
-       return ret;
-}
-
-/* No need to check for holes in the mask for the lowest mode */
-static int omap_prm_domain_find_lowest(struct omap_prm_domain *prmd)
-{
-       return __ffs(prmd->cap->usable_modes);
-}
-
-static int omap_prm_domain_power_off(struct generic_pm_domain *domain)
-{
-       struct omap_prm_domain *prmd;
-       int ret;
-       u32 v;
-
-       prmd = genpd_to_prm_domain(domain);
-       if (!prmd->cap)
-               return 0;
-
-       omap_prm_domain_show_state(prmd, "off: previous state");
-
-       v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl);
-       prmd->pwrstctrl_saved = v;
-
-       v &= ~PRM_POWERSTATE_MASK;
-       v |= omap_prm_domain_find_lowest(prmd);
-
-       if (prmd->cap->statechange)
-               v |= PRM_LOWPOWERSTATECHANGE;
-       if (prmd->cap->logicretstate)
-               v &= ~PRM_LOGICRETSTATE;
-       else
-               v |= PRM_LOGICRETSTATE;
-
-       writel_relaxed(v, prmd->prm->base + prmd->pwrstctrl);
-
-       /* wait for the transition bit to get cleared */
-       ret = readl_relaxed_poll_timeout(prmd->prm->base + prmd->pwrstst,
-                                        v, !(v & PRM_ST_INTRANSITION), 1,
-                                        PRM_STATE_MAX_WAIT);
-       if (ret)
-               dev_warn(prmd->dev, "%s: %s timed out\n",
-                        __func__, prmd->pd.name);
-
-       omap_prm_domain_show_state(prmd, "off: new state");
-
-       return 0;
-}
-
-/*
- * Note that ti-sysc already manages the module clocks separately so
- * no need to manage those. Interconnect instances need clocks managed
- * for simple-pm-bus.
- */
-static int omap_prm_domain_attach_clock(struct device *dev,
-                                       struct omap_prm_domain *prmd)
-{
-       struct device_node *np = dev->of_node;
-       int error;
-
-       if (!of_device_is_compatible(np, "simple-pm-bus"))
-               return 0;
-
-       if (!of_property_read_bool(np, "clocks"))
-               return 0;
-
-       error = pm_clk_create(dev);
-       if (error)
-               return error;
-
-       error = of_pm_clk_add_clks(dev);
-       if (error < 0) {
-               pm_clk_destroy(dev);
-               return error;
-       }
-
-       prmd->uses_pm_clk = 1;
-
-       return 0;
-}
-
-static int omap_prm_domain_attach_dev(struct generic_pm_domain *domain,
-                                     struct device *dev)
-{
-       struct generic_pm_domain_data *genpd_data;
-       struct of_phandle_args pd_args;
-       struct omap_prm_domain *prmd;
-       struct device_node *np;
-       int ret;
-
-       prmd = genpd_to_prm_domain(domain);
-       np = dev->of_node;
-
-       ret = of_parse_phandle_with_args(np, "power-domains",
-                                        "#power-domain-cells", 0, &pd_args);
-       if (ret < 0)
-               return ret;
-
-       if (pd_args.args_count != 0)
-               dev_warn(dev, "%s: unusupported #power-domain-cells: %i\n",
-                        prmd->pd.name, pd_args.args_count);
-
-       genpd_data = dev_gpd_data(dev);
-       genpd_data->data = NULL;
-
-       ret = omap_prm_domain_attach_clock(dev, prmd);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
-static void omap_prm_domain_detach_dev(struct generic_pm_domain *domain,
-                                      struct device *dev)
-{
-       struct generic_pm_domain_data *genpd_data;
-       struct omap_prm_domain *prmd;
-
-       prmd = genpd_to_prm_domain(domain);
-       if (prmd->uses_pm_clk)
-               pm_clk_destroy(dev);
-       genpd_data = dev_gpd_data(dev);
-       genpd_data->data = NULL;
-}
-
-static int omap_prm_domain_init(struct device *dev, struct omap_prm *prm)
-{
-       struct omap_prm_domain *prmd;
-       struct device_node *np = dev->of_node;
-       const struct omap_prm_data *data;
-       const char *name;
-       int error;
-
-       if (!of_property_present(dev->of_node, "#power-domain-cells"))
-               return 0;
-
-       of_node_put(dev->of_node);
-
-       prmd = devm_kzalloc(dev, sizeof(*prmd), GFP_KERNEL);
-       if (!prmd)
-               return -ENOMEM;
-
-       data = prm->data;
-       name = devm_kasprintf(dev, GFP_KERNEL, "prm_%s",
-                             data->name);
-
-       prmd->dev = dev;
-       prmd->prm = prm;
-       prmd->cap = prmd->prm->data->dmap;
-       prmd->pwrstctrl = prmd->prm->data->pwrstctrl;
-       prmd->pwrstst = prmd->prm->data->pwrstst;
-
-       prmd->pd.name = name;
-       prmd->pd.power_on = omap_prm_domain_power_on;
-       prmd->pd.power_off = omap_prm_domain_power_off;
-       prmd->pd.attach_dev = omap_prm_domain_attach_dev;
-       prmd->pd.detach_dev = omap_prm_domain_detach_dev;
-       prmd->pd.flags = GENPD_FLAG_PM_CLK;
-
-       pm_genpd_init(&prmd->pd, NULL, true);
-       error = of_genpd_add_provider_simple(np, &prmd->pd);
-       if (error)
-               pm_genpd_remove(&prmd->pd);
-       else
-               prm->prmd = prmd;
-
-       return error;
-}
-
-static bool _is_valid_reset(struct omap_reset_data *reset, unsigned long id)
-{
-       if (reset->mask & BIT(id))
-               return true;
-
-       return false;
-}
-
-static int omap_reset_get_st_bit(struct omap_reset_data *reset,
-                                unsigned long id)
-{
-       const struct omap_rst_map *map = reset->prm->data->rstmap;
-
-       while (map->rst >= 0) {
-               if (map->rst == id)
-                       return map->st;
-
-               map++;
-       }
-
-       return id;
-}
-
-static int omap_reset_status(struct reset_controller_dev *rcdev,
-                            unsigned long id)
-{
-       struct omap_reset_data *reset = to_omap_reset_data(rcdev);
-       u32 v;
-       int st_bit = omap_reset_get_st_bit(reset, id);
-       bool has_rstst = reset->prm->data->rstst ||
-               (reset->prm->data->flags & OMAP_PRM_HAS_RSTST);
-
-       /* Check if we have rstst */
-       if (!has_rstst)
-               return -ENOTSUPP;
-
-       /* Check if hw reset line is asserted */
-       v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
-       if (v & BIT(id))
-               return 1;
-
-       /*
-        * Check reset status, high value means reset sequence has been
-        * completed successfully so we can return 0 here (reset deasserted)
-        */
-       v = readl_relaxed(reset->prm->base + reset->prm->data->rstst);
-       v >>= st_bit;
-       v &= 1;
-
-       return !v;
-}
-
-static int omap_reset_assert(struct reset_controller_dev *rcdev,
-                            unsigned long id)
-{
-       struct omap_reset_data *reset = to_omap_reset_data(rcdev);
-       u32 v;
-       unsigned long flags;
-
-       /* assert the reset control line */
-       spin_lock_irqsave(&reset->lock, flags);
-       v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
-       v |= 1 << id;
-       writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl);
-       spin_unlock_irqrestore(&reset->lock, flags);
-
-       return 0;
-}
-
-static int omap_reset_deassert(struct reset_controller_dev *rcdev,
-                              unsigned long id)
-{
-       struct omap_reset_data *reset = to_omap_reset_data(rcdev);
-       u32 v;
-       int st_bit;
-       bool has_rstst;
-       unsigned long flags;
-       struct ti_prm_platform_data *pdata = dev_get_platdata(reset->dev);
-       int ret = 0;
-
-       /* Nothing to do if the reset is already deasserted */
-       if (!omap_reset_status(rcdev, id))
-               return 0;
-
-       has_rstst = reset->prm->data->rstst ||
-               (reset->prm->data->flags & OMAP_PRM_HAS_RSTST);
-
-       if (has_rstst) {
-               st_bit = omap_reset_get_st_bit(reset, id);
-
-               /* Clear the reset status by writing 1 to the status bit */
-               v = 1 << st_bit;
-               writel_relaxed(v, reset->prm->base + reset->prm->data->rstst);
-       }
-
-       if (reset->clkdm)
-               pdata->clkdm_deny_idle(reset->clkdm);
-
-       /* de-assert the reset control line */
-       spin_lock_irqsave(&reset->lock, flags);
-       v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
-       v &= ~(1 << id);
-       writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl);
-       spin_unlock_irqrestore(&reset->lock, flags);
-
-       /* wait for the reset bit to clear */
-       ret = readl_relaxed_poll_timeout_atomic(reset->prm->base +
-                                               reset->prm->data->rstctrl,
-                                               v, !(v & BIT(id)), 1,
-                                               OMAP_RESET_MAX_WAIT);
-       if (ret)
-               pr_err("%s: timedout waiting for %s:%lu\n", __func__,
-                      reset->prm->data->name, id);
-
-       /* wait for the status to be set */
-       if (has_rstst) {
-               ret = readl_relaxed_poll_timeout_atomic(reset->prm->base +
-                                                reset->prm->data->rstst,
-                                                v, v & BIT(st_bit), 1,
-                                                OMAP_RESET_MAX_WAIT);
-               if (ret)
-                       pr_err("%s: timedout waiting for %s:%lu\n", __func__,
-                              reset->prm->data->name, id);
-       }
-
-       if (reset->clkdm)
-               pdata->clkdm_allow_idle(reset->clkdm);
-
-       return ret;
-}
-
-static const struct reset_control_ops omap_reset_ops = {
-       .assert         = omap_reset_assert,
-       .deassert       = omap_reset_deassert,
-       .status         = omap_reset_status,
-};
-
-static int omap_prm_reset_xlate(struct reset_controller_dev *rcdev,
-                               const struct of_phandle_args *reset_spec)
-{
-       struct omap_reset_data *reset = to_omap_reset_data(rcdev);
-
-       if (!_is_valid_reset(reset, reset_spec->args[0]))
-               return -EINVAL;
-
-       return reset_spec->args[0];
-}
-
-static int omap_prm_reset_init(struct platform_device *pdev,
-                              struct omap_prm *prm)
-{
-       struct omap_reset_data *reset;
-       const struct omap_rst_map *map;
-       struct ti_prm_platform_data *pdata = dev_get_platdata(&pdev->dev);
-       char buf[32];
-       u32 v;
-
-       /*
-        * Check if we have controllable resets. If either rstctrl is non-zero
-        * or OMAP_PRM_HAS_RSTCTRL flag is set, we have reset control register
-        * for the domain.
-        */
-       if (!prm->data->rstctrl && !(prm->data->flags & OMAP_PRM_HAS_RSTCTRL))
-               return 0;
-
-       /* Check if we have the pdata callbacks in place */
-       if (!pdata || !pdata->clkdm_lookup || !pdata->clkdm_deny_idle ||
-           !pdata->clkdm_allow_idle)
-               return -EINVAL;
-
-       map = prm->data->rstmap;
-       if (!map)
-               return -EINVAL;
-
-       reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
-       if (!reset)
-               return -ENOMEM;
-
-       reset->rcdev.owner = THIS_MODULE;
-       reset->rcdev.ops = &omap_reset_ops;
-       reset->rcdev.of_node = pdev->dev.of_node;
-       reset->rcdev.nr_resets = OMAP_MAX_RESETS;
-       reset->rcdev.of_xlate = omap_prm_reset_xlate;
-       reset->rcdev.of_reset_n_cells = 1;
-       reset->dev = &pdev->dev;
-       spin_lock_init(&reset->lock);
-
-       reset->prm = prm;
-
-       sprintf(buf, "%s_clkdm", prm->data->clkdm_name ? prm->data->clkdm_name :
-               prm->data->name);
-
-       if (!(prm->data->flags & OMAP_PRM_HAS_NO_CLKDM)) {
-               reset->clkdm = pdata->clkdm_lookup(buf);
-               if (!reset->clkdm)
-                       return -EINVAL;
-       }
-
-       while (map->rst >= 0) {
-               reset->mask |= BIT(map->rst);
-               map++;
-       }
-
-       /* Quirk handling to assert rst_map_012 bits on reset and avoid errors */
-       if (prm->data->rstmap == rst_map_012) {
-               v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
-               if ((v & reset->mask) != reset->mask) {
-                       dev_dbg(&pdev->dev, "Asserting all resets: %08x\n", v);
-                       writel_relaxed(reset->mask, reset->prm->base +
-                                      reset->prm->data->rstctrl);
-               }
-       }
-
-       return devm_reset_controller_register(&pdev->dev, &reset->rcdev);
-}
-
-static int omap_prm_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       const struct omap_prm_data *data;
-       struct omap_prm *prm;
-       int ret;
-
-       data = of_device_get_match_data(&pdev->dev);
-       if (!data)
-               return -ENOTSUPP;
-
-       prm = devm_kzalloc(&pdev->dev, sizeof(*prm), GFP_KERNEL);
-       if (!prm)
-               return -ENOMEM;
-
-       prm->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
-       if (IS_ERR(prm->base))
-               return PTR_ERR(prm->base);
-
-       while (data->base != res->start) {
-               if (!data->base)
-                       return -EINVAL;
-               data++;
-       }
-
-       prm->data = data;
-
-       ret = omap_prm_domain_init(&pdev->dev, prm);
-       if (ret)
-               return ret;
-
-       ret = omap_prm_reset_init(pdev, prm);
-       if (ret)
-               goto err_domain;
-
-       return 0;
-
-err_domain:
-       of_genpd_del_provider(pdev->dev.of_node);
-       pm_genpd_remove(&prm->prmd->pd);
-
-       return ret;
-}
-
-static struct platform_driver omap_prm_driver = {
-       .probe = omap_prm_probe,
-       .driver = {
-               .name           = KBUILD_MODNAME,
-               .of_match_table = omap_prm_id_table,
-       },
-};
-builtin_platform_driver(omap_prm_driver);
diff --git a/drivers/genpd/ti/ti_sci_pm_domains.c b/drivers/genpd/ti/ti_sci_pm_domains.c
deleted file mode 100644 (file)
index 3464510..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * TI SCI Generic Power Domain Driver
- *
- * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
- *     J Keerthy <j-keerthy@ti.com>
- *     Dave Gerlach <d-gerlach@ti.com>
- */
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/slab.h>
-#include <linux/soc/ti/ti_sci_protocol.h>
-#include <dt-bindings/soc/ti,sci_pm_domain.h>
-
-/**
- * struct ti_sci_genpd_provider: holds common TI SCI genpd provider data
- * @ti_sci: handle to TI SCI protocol driver that provides ops to
- *         communicate with system control processor.
- * @dev: pointer to dev for the driver for devm allocs
- * @pd_list: list of all the power domains on the device
- * @data: onecell data for genpd core
- */
-struct ti_sci_genpd_provider {
-       const struct ti_sci_handle *ti_sci;
-       struct device *dev;
-       struct list_head pd_list;
-       struct genpd_onecell_data data;
-};
-
-/**
- * struct ti_sci_pm_domain: TI specific data needed for power domain
- * @idx: index of the device that identifies it with the system
- *      control processor.
- * @exclusive: Permissions for exclusive request or shared request of the
- *            device.
- * @pd: generic_pm_domain for use with the genpd framework
- * @node: link for the genpd list
- * @parent: link to the parent TI SCI genpd provider
- */
-struct ti_sci_pm_domain {
-       int idx;
-       u8 exclusive;
-       struct generic_pm_domain pd;
-       struct list_head node;
-       struct ti_sci_genpd_provider *parent;
-};
-
-#define genpd_to_ti_sci_pd(gpd) container_of(gpd, struct ti_sci_pm_domain, pd)
-
-/*
- * ti_sci_pd_power_off(): genpd power down hook
- * @domain: pointer to the powerdomain to power off
- */
-static int ti_sci_pd_power_off(struct generic_pm_domain *domain)
-{
-       struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(domain);
-       const struct ti_sci_handle *ti_sci = pd->parent->ti_sci;
-
-       return ti_sci->ops.dev_ops.put_device(ti_sci, pd->idx);
-}
-
-/*
- * ti_sci_pd_power_on(): genpd power up hook
- * @domain: pointer to the powerdomain to power on
- */
-static int ti_sci_pd_power_on(struct generic_pm_domain *domain)
-{
-       struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(domain);
-       const struct ti_sci_handle *ti_sci = pd->parent->ti_sci;
-
-       if (pd->exclusive)
-               return ti_sci->ops.dev_ops.get_device_exclusive(ti_sci,
-                                                               pd->idx);
-       else
-               return ti_sci->ops.dev_ops.get_device(ti_sci, pd->idx);
-}
-
-/*
- * ti_sci_pd_xlate(): translation service for TI SCI genpds
- * @genpdspec: DT identification data for the genpd
- * @data: genpd core data for all the powerdomains on the device
- */
-static struct generic_pm_domain *ti_sci_pd_xlate(
-                                       struct of_phandle_args *genpdspec,
-                                       void *data)
-{
-       struct genpd_onecell_data *genpd_data = data;
-       unsigned int idx = genpdspec->args[0];
-
-       if (genpdspec->args_count != 1 && genpdspec->args_count != 2)
-               return ERR_PTR(-EINVAL);
-
-       if (idx >= genpd_data->num_domains) {
-               pr_err("%s: invalid domain index %u\n", __func__, idx);
-               return ERR_PTR(-EINVAL);
-       }
-
-       if (!genpd_data->domains[idx])
-               return ERR_PTR(-ENOENT);
-
-       genpd_to_ti_sci_pd(genpd_data->domains[idx])->exclusive =
-               genpdspec->args[1];
-
-       return genpd_data->domains[idx];
-}
-
-static const struct of_device_id ti_sci_pm_domain_matches[] = {
-       { .compatible = "ti,sci-pm-domain", },
-       { },
-};
-MODULE_DEVICE_TABLE(of, ti_sci_pm_domain_matches);
-
-static int ti_sci_pm_domain_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct ti_sci_genpd_provider *pd_provider;
-       struct ti_sci_pm_domain *pd;
-       struct device_node *np;
-       struct of_phandle_args args;
-       int ret;
-       u32 max_id = 0;
-       int index;
-
-       pd_provider = devm_kzalloc(dev, sizeof(*pd_provider), GFP_KERNEL);
-       if (!pd_provider)
-               return -ENOMEM;
-
-       pd_provider->ti_sci = devm_ti_sci_get_handle(dev);
-       if (IS_ERR(pd_provider->ti_sci))
-               return PTR_ERR(pd_provider->ti_sci);
-
-       pd_provider->dev = dev;
-
-       INIT_LIST_HEAD(&pd_provider->pd_list);
-
-       /* Find highest device ID used for power domains */
-       for_each_node_with_property(np, "power-domains") {
-               index = 0;
-
-               while (1) {
-                       ret = of_parse_phandle_with_args(np, "power-domains",
-                                                        "#power-domain-cells",
-                                                        index, &args);
-                       if (ret)
-                               break;
-
-                       if (args.args_count >= 1 && args.np == dev->of_node) {
-                               if (args.args[0] > max_id)
-                                       max_id = args.args[0];
-
-                               pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
-                               if (!pd)
-                                       return -ENOMEM;
-
-                               pd->pd.name = devm_kasprintf(dev, GFP_KERNEL,
-                                                            "pd:%d",
-                                                            args.args[0]);
-                               if (!pd->pd.name)
-                                       return -ENOMEM;
-
-                               pd->pd.power_off = ti_sci_pd_power_off;
-                               pd->pd.power_on = ti_sci_pd_power_on;
-                               pd->idx = args.args[0];
-                               pd->parent = pd_provider;
-
-                               pm_genpd_init(&pd->pd, NULL, true);
-
-                               list_add(&pd->node, &pd_provider->pd_list);
-                       }
-                       index++;
-               }
-       }
-
-       pd_provider->data.domains =
-               devm_kcalloc(dev, max_id + 1,
-                            sizeof(*pd_provider->data.domains),
-                            GFP_KERNEL);
-       if (!pd_provider->data.domains)
-               return -ENOMEM;
-
-       pd_provider->data.num_domains = max_id + 1;
-       pd_provider->data.xlate = ti_sci_pd_xlate;
-
-       list_for_each_entry(pd, &pd_provider->pd_list, node)
-               pd_provider->data.domains[pd->idx] = &pd->pd;
-
-       return of_genpd_add_provider_onecell(dev->of_node, &pd_provider->data);
-}
-
-static struct platform_driver ti_sci_pm_domains_driver = {
-       .probe = ti_sci_pm_domain_probe,
-       .driver = {
-               .name = "ti_sci_pm_domains",
-               .of_match_table = ti_sci_pm_domain_matches,
-       },
-};
-module_platform_driver(ti_sci_pm_domains_driver);
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("TI System Control Interface (SCI) Power Domain driver");
-MODULE_AUTHOR("Dave Gerlach");
diff --git a/drivers/genpd/xilinx/Makefile b/drivers/genpd/xilinx/Makefile
deleted file mode 100644 (file)
index a706ab6..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_ZYNQMP_PM_DOMAINS)                += zynqmp-pm-domains.o
diff --git a/drivers/genpd/xilinx/zynqmp-pm-domains.c b/drivers/genpd/xilinx/zynqmp-pm-domains.c
deleted file mode 100644 (file)
index 69d03ad..0000000
+++ /dev/null
@@ -1,322 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * ZynqMP Generic PM domain support
- *
- *  Copyright (C) 2015-2019 Xilinx, Inc.
- *
- *  Davorin Mista <davorin.mista@aggios.com>
- *  Jolly Shah <jollys@xilinx.com>
- *  Rajan Vaja <rajan.vaja@xilinx.com>
- */
-
-#include <linux/err.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/slab.h>
-
-#include <linux/firmware/xlnx-zynqmp.h>
-
-#define ZYNQMP_NUM_DOMAINS             (100)
-
-static int min_capability;
-
-/**
- * struct zynqmp_pm_domain - Wrapper around struct generic_pm_domain
- * @gpd:               Generic power domain
- * @node_id:           PM node ID corresponding to device inside PM domain
- * @requested:         The PM node mapped to the PM domain has been requested
- */
-struct zynqmp_pm_domain {
-       struct generic_pm_domain gpd;
-       u32 node_id;
-       bool requested;
-};
-
-#define to_zynqmp_pm_domain(pm_domain) \
-       container_of(pm_domain, struct zynqmp_pm_domain, gpd)
-
-/**
- * zynqmp_gpd_is_active_wakeup_path() - Check if device is in wakeup source
- *                                     path
- * @dev:       Device to check for wakeup source path
- * @not_used:  Data member (not required)
- *
- * This function is checks device's child hierarchy and checks if any device is
- * set as wakeup source.
- *
- * Return: 1 if device is in wakeup source path else 0
- */
-static int zynqmp_gpd_is_active_wakeup_path(struct device *dev, void *not_used)
-{
-       int may_wakeup;
-
-       may_wakeup = device_may_wakeup(dev);
-       if (may_wakeup)
-               return may_wakeup;
-
-       return device_for_each_child(dev, NULL,
-                       zynqmp_gpd_is_active_wakeup_path);
-}
-
-/**
- * zynqmp_gpd_power_on() - Power on PM domain
- * @domain:    Generic PM domain
- *
- * This function is called before devices inside a PM domain are resumed, to
- * power on PM domain.
- *
- * Return: 0 on success, error code otherwise
- */
-static int zynqmp_gpd_power_on(struct generic_pm_domain *domain)
-{
-       struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain);
-       int ret;
-
-       ret = zynqmp_pm_set_requirement(pd->node_id,
-                                       ZYNQMP_PM_CAPABILITY_ACCESS,
-                                       ZYNQMP_PM_MAX_QOS,
-                                       ZYNQMP_PM_REQUEST_ACK_BLOCKING);
-       if (ret) {
-               dev_err(&domain->dev,
-                       "failed to set requirement to 0x%x for PM node id %d: %d\n",
-                       ZYNQMP_PM_CAPABILITY_ACCESS, pd->node_id, ret);
-               return ret;
-       }
-
-       dev_dbg(&domain->dev, "set requirement to 0x%x for PM node id %d\n",
-               ZYNQMP_PM_CAPABILITY_ACCESS, pd->node_id);
-
-       return 0;
-}
-
-/**
- * zynqmp_gpd_power_off() - Power off PM domain
- * @domain:    Generic PM domain
- *
- * This function is called after devices inside a PM domain are suspended, to
- * power off PM domain.
- *
- * Return: 0 on success, error code otherwise
- */
-static int zynqmp_gpd_power_off(struct generic_pm_domain *domain)
-{
-       struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain);
-       int ret;
-       struct pm_domain_data *pdd, *tmp;
-       u32 capabilities = min_capability;
-       bool may_wakeup;
-
-       /* If domain is already released there is nothing to be done */
-       if (!pd->requested) {
-               dev_dbg(&domain->dev, "PM node id %d is already released\n",
-                       pd->node_id);
-               return 0;
-       }
-
-       list_for_each_entry_safe(pdd, tmp, &domain->dev_list, list_node) {
-               /* If device is in wakeup path, set capability to WAKEUP */
-               may_wakeup = zynqmp_gpd_is_active_wakeup_path(pdd->dev, NULL);
-               if (may_wakeup) {
-                       dev_dbg(pdd->dev, "device is in wakeup path in %s\n",
-                               domain->name);
-                       capabilities = ZYNQMP_PM_CAPABILITY_WAKEUP;
-                       break;
-               }
-       }
-
-       ret = zynqmp_pm_set_requirement(pd->node_id, capabilities, 0,
-                                       ZYNQMP_PM_REQUEST_ACK_NO);
-       if (ret) {
-               dev_err(&domain->dev,
-                       "failed to set requirement to 0x%x for PM node id %d: %d\n",
-                       capabilities, pd->node_id, ret);
-               return ret;
-       }
-
-       dev_dbg(&domain->dev, "set requirement to 0x%x for PM node id %d\n",
-               capabilities, pd->node_id);
-
-       return 0;
-}
-
-/**
- * zynqmp_gpd_attach_dev() - Attach device to the PM domain
- * @domain:    Generic PM domain
- * @dev:       Device to attach
- *
- * Return: 0 on success, error code otherwise
- */
-static int zynqmp_gpd_attach_dev(struct generic_pm_domain *domain,
-                                struct device *dev)
-{
-       struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain);
-       struct device_link *link;
-       int ret;
-
-       link = device_link_add(dev, &domain->dev, DL_FLAG_SYNC_STATE_ONLY);
-       if (!link)
-               dev_dbg(&domain->dev, "failed to create device link for %s\n",
-                       dev_name(dev));
-
-       /* If this is not the first device to attach there is nothing to do */
-       if (domain->device_count)
-               return 0;
-
-       ret = zynqmp_pm_request_node(pd->node_id, 0, 0,
-                                    ZYNQMP_PM_REQUEST_ACK_BLOCKING);
-       if (ret) {
-               dev_err(&domain->dev, "%s request failed for node %d: %d\n",
-                       domain->name, pd->node_id, ret);
-               return ret;
-       }
-
-       pd->requested = true;
-
-       dev_dbg(&domain->dev, "%s requested PM node id %d\n",
-               dev_name(dev), pd->node_id);
-
-       return 0;
-}
-
-/**
- * zynqmp_gpd_detach_dev() - Detach device from the PM domain
- * @domain:    Generic PM domain
- * @dev:       Device to detach
- */
-static void zynqmp_gpd_detach_dev(struct generic_pm_domain *domain,
-                                 struct device *dev)
-{
-       struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain);
-       int ret;
-
-       /* If this is not the last device to detach there is nothing to do */
-       if (domain->device_count)
-               return;
-
-       ret = zynqmp_pm_release_node(pd->node_id);
-       if (ret) {
-               dev_err(&domain->dev, "failed to release PM node id %d: %d\n",
-                       pd->node_id, ret);
-               return;
-       }
-
-       pd->requested = false;
-
-       dev_dbg(&domain->dev, "%s released PM node id %d\n",
-               dev_name(dev), pd->node_id);
-}
-
-static struct generic_pm_domain *zynqmp_gpd_xlate
-                               (struct of_phandle_args *genpdspec, void *data)
-{
-       struct genpd_onecell_data *genpd_data = data;
-       unsigned int i, idx = genpdspec->args[0];
-       struct zynqmp_pm_domain *pd;
-
-       pd = to_zynqmp_pm_domain(genpd_data->domains[0]);
-
-       if (genpdspec->args_count != 1)
-               return ERR_PTR(-EINVAL);
-
-       /* Check for existing pm domains */
-       for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++) {
-               if (pd[i].node_id == idx)
-                       goto done;
-       }
-
-       /*
-        * Add index in empty node_id of power domain list as no existing
-        * power domain found for current index.
-        */
-       for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++) {
-               if (pd[i].node_id == 0) {
-                       pd[i].node_id = idx;
-                       break;
-               }
-       }
-
-done:
-       if (!genpd_data->domains[i] || i == ZYNQMP_NUM_DOMAINS)
-               return ERR_PTR(-ENOENT);
-
-       return genpd_data->domains[i];
-}
-
-static int zynqmp_gpd_probe(struct platform_device *pdev)
-{
-       int i;
-       struct genpd_onecell_data *zynqmp_pd_data;
-       struct generic_pm_domain **domains;
-       struct zynqmp_pm_domain *pd;
-       struct device *dev = &pdev->dev;
-
-       pd = devm_kcalloc(dev, ZYNQMP_NUM_DOMAINS, sizeof(*pd), GFP_KERNEL);
-       if (!pd)
-               return -ENOMEM;
-
-       zynqmp_pd_data = devm_kzalloc(dev, sizeof(*zynqmp_pd_data), GFP_KERNEL);
-       if (!zynqmp_pd_data)
-               return -ENOMEM;
-
-       zynqmp_pd_data->xlate = zynqmp_gpd_xlate;
-
-       domains = devm_kcalloc(dev, ZYNQMP_NUM_DOMAINS, sizeof(*domains),
-                              GFP_KERNEL);
-       if (!domains)
-               return -ENOMEM;
-
-       if (!of_device_is_compatible(dev->parent->of_node,
-                                    "xlnx,zynqmp-firmware"))
-               min_capability = ZYNQMP_PM_CAPABILITY_UNUSABLE;
-
-       for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++, pd++) {
-               pd->node_id = 0;
-               pd->gpd.name = kasprintf(GFP_KERNEL, "domain%d", i);
-               pd->gpd.power_off = zynqmp_gpd_power_off;
-               pd->gpd.power_on = zynqmp_gpd_power_on;
-               pd->gpd.attach_dev = zynqmp_gpd_attach_dev;
-               pd->gpd.detach_dev = zynqmp_gpd_detach_dev;
-
-               domains[i] = &pd->gpd;
-
-               /* Mark all PM domains as initially powered off */
-               pm_genpd_init(&pd->gpd, NULL, true);
-       }
-
-       zynqmp_pd_data->domains = domains;
-       zynqmp_pd_data->num_domains = ZYNQMP_NUM_DOMAINS;
-       of_genpd_add_provider_onecell(dev->parent->of_node, zynqmp_pd_data);
-
-       return 0;
-}
-
-static int zynqmp_gpd_remove(struct platform_device *pdev)
-{
-       of_genpd_del_provider(pdev->dev.parent->of_node);
-
-       return 0;
-}
-
-static void zynqmp_gpd_sync_state(struct device *dev)
-{
-       int ret;
-
-       ret = zynqmp_pm_init_finalize();
-       if (ret)
-               dev_warn(dev, "failed to release power management to firmware\n");
-}
-
-static struct platform_driver zynqmp_power_domain_driver = {
-       .driver = {
-               .name = "zynqmp_power_controller",
-               .sync_state = zynqmp_gpd_sync_state,
-       },
-       .probe = zynqmp_gpd_probe,
-       .remove = zynqmp_gpd_remove,
-};
-module_platform_driver(zynqmp_power_domain_driver);
-
-MODULE_ALIAS("platform:zynqmp_power_controller");
index 271db3639a78209e00d45d558d6354bb0161e27f..44bf1709a6488cd7e61eca8e56463f670bbee4b8 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/irq.h>
 #include <linux/irq_sim.h>
 #include <linux/list.h>
+#include <linux/minmax.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -685,52 +686,32 @@ gpio_sim_device_config_live_show(struct config_item *item, char *page)
        return sprintf(page, "%c\n", live ? '1' : '0');
 }
 
-static char **gpio_sim_make_line_names(struct gpio_sim_bank *bank,
-                                      unsigned int *line_names_size)
+static unsigned int gpio_sim_get_line_names_size(struct gpio_sim_bank *bank)
 {
-       unsigned int max_offset = 0;
-       bool has_line_names = false;
        struct gpio_sim_line *line;
-       char **line_names;
+       unsigned int size = 0;
 
        list_for_each_entry(line, &bank->line_list, siblings) {
-               if (line->offset >= bank->num_lines)
+               if (!line->name || (line->offset >= bank->num_lines))
                        continue;
 
-               if (line->name) {
-                       if (line->offset > max_offset)
-                               max_offset = line->offset;
-
-                       /*
-                        * max_offset can stay at 0 so it's not an indicator
-                        * of whether line names were configured at all.
-                        */
-                       has_line_names = true;
-               }
+               size = max(size, line->offset + 1);
        }
 
-       if (!has_line_names)
-               /*
-                * This is not an error - NULL means, there are no line
-                * names configured.
-                */
-               return NULL;
-
-       *line_names_size = max_offset + 1;
+       return size;
+}
 
-       line_names = kcalloc(*line_names_size, sizeof(*line_names), GFP_KERNEL);
-       if (!line_names)
-               return ERR_PTR(-ENOMEM);
+static void
+gpio_sim_set_line_names(struct gpio_sim_bank *bank, char **line_names)
+{
+       struct gpio_sim_line *line;
 
        list_for_each_entry(line, &bank->line_list, siblings) {
-               if (line->offset >= bank->num_lines)
+               if (!line->name || (line->offset >= bank->num_lines))
                        continue;
 
-               if (line->name && (line->offset <= max_offset))
-                       line_names[line->offset] = line->name;
+               line_names[line->offset] = line->name;
        }
-
-       return line_names;
 }
 
 static void gpio_sim_remove_hogs(struct gpio_sim_device *dev)
@@ -834,7 +815,7 @@ gpio_sim_make_bank_swnode(struct gpio_sim_bank *bank,
                          struct fwnode_handle *parent)
 {
        struct property_entry properties[GPIO_SIM_PROP_MAX];
-       unsigned int prop_idx = 0, line_names_size = 0;
+       unsigned int prop_idx = 0, line_names_size;
        char **line_names __free(kfree) = NULL;
 
        memset(properties, 0, sizeof(properties));
@@ -845,14 +826,19 @@ gpio_sim_make_bank_swnode(struct gpio_sim_bank *bank,
                properties[prop_idx++] = PROPERTY_ENTRY_STRING("gpio-sim,label",
                                                               bank->label);
 
-       line_names = gpio_sim_make_line_names(bank, &line_names_size);
-       if (IS_ERR(line_names))
-               return ERR_CAST(line_names);
+       line_names_size = gpio_sim_get_line_names_size(bank);
+       if (line_names_size) {
+               line_names = kcalloc(line_names_size, sizeof(*line_names),
+                                    GFP_KERNEL);
+               if (!line_names)
+                       return ERR_PTR(-ENOMEM);
+
+               gpio_sim_set_line_names(bank, line_names);
 
-       if (line_names)
                properties[prop_idx++] = PROPERTY_ENTRY_STRING_ARRAY_LEN(
                                                "gpio-line-names",
                                                line_names, line_names_size);
+       }
 
        return fwnode_create_software_node(properties, parent);
 }
index 78f8790168ae1e4bad29229970cec99ff6f52d9b..f96d260a4a19d8b788dbf92aef7da5c4e0bfcb63 100644 (file)
@@ -195,7 +195,7 @@ static int tb10x_gpio_probe(struct platform_device *pdev)
                                handle_edge_irq, IRQ_NOREQUEST, IRQ_NOPROBE,
                                IRQ_GC_INIT_MASK_CACHE);
                if (ret)
-                       return ret;
+                       goto err_remove_domain;
 
                gc = tb10x_gpio->domain->gc->gc[0];
                gc->reg_base                         = tb10x_gpio->base;
@@ -209,6 +209,10 @@ static int tb10x_gpio_probe(struct platform_device *pdev)
        }
 
        return 0;
+
+err_remove_domain:
+       irq_domain_remove(tb10x_gpio->domain);
+       return ret;
 }
 
 static int tb10x_gpio_remove(struct platform_device *pdev)
index ab9ef1c2034912d8fc330f6009a81dc31759f5b5..3caa020391c75283c9145d18fb3be151496620af 100644 (file)
@@ -136,7 +136,7 @@ config DRM_FBDEV_EMULATION
        bool "Enable legacy fbdev support for your modesetting driver"
        depends on DRM
        select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if FRAMEBUFFER_CONSOLE
-       default y
+       default FB
        help
          Choose this option if you have a need for the legacy fbdev
          support. Note that this support also provides the linux console
index dc2d53081e806ffcdb05bc32e46cb76cdaed056c..a79d53bdbe136a8a99afe83530d5666d2edb405f 100644 (file)
@@ -1293,7 +1293,6 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
 void amdgpu_device_pci_config_reset(struct amdgpu_device *adev);
 int amdgpu_device_pci_reset(struct amdgpu_device *adev);
 bool amdgpu_device_need_post(struct amdgpu_device *adev);
-bool amdgpu_sg_display_supported(struct amdgpu_device *adev);
 bool amdgpu_device_pcie_dynamic_switching_supported(void);
 bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev);
 bool amdgpu_device_aspm_support_quirk(void);
index cdf6087706aa832a3cd6c67378877b50be9f1910..25d5fda5b243e3c598c141952f9537fe3c9652d7 100644 (file)
@@ -478,7 +478,7 @@ void amdgpu_amdkfd_get_cu_info(struct amdgpu_device *adev, struct kfd_cu_info *c
        cu_info->cu_active_number = acu_info.number;
        cu_info->cu_ao_mask = acu_info.ao_cu_mask;
        memcpy(&cu_info->cu_bitmap[0], &acu_info.bitmap[0],
-              sizeof(acu_info.bitmap));
+              sizeof(cu_info->cu_bitmap));
        cu_info->num_shader_engines = adev->gfx.config.max_shader_engines;
        cu_info->num_shader_arrays_per_engine = adev->gfx.config.max_sh_per_se;
        cu_info->num_cu_per_sh = adev->gfx.config.max_cu_per_sh;
index f1f2c24de081eb1f300b2664a53f221591f50e06..69810b3f1c63613f6686f181cdeccf5d9513c2d9 100644 (file)
@@ -980,8 +980,7 @@ void kgd_gfx_v10_build_grace_period_packet_info(struct amdgpu_device *adev,
                                                uint32_t wait_times,
                                                uint32_t grace_period,
                                                uint32_t *reg_offset,
-                                               uint32_t *reg_data,
-                                               uint32_t inst)
+                                               uint32_t *reg_data)
 {
        *reg_data = wait_times;
 
index ecaead24e8c96bbe288fffcac96b067f33fb1589..67bcaa3d4226410279a6bce1b62b7e0cd206259f 100644 (file)
@@ -55,5 +55,4 @@ void kgd_gfx_v10_build_grace_period_packet_info(struct amdgpu_device *adev,
                                               uint32_t wait_times,
                                               uint32_t grace_period,
                                               uint32_t *reg_offset,
-                                              uint32_t *reg_data,
-                                              uint32_t inst);
+                                              uint32_t *reg_data);
index fa5ee96f884545c6fe6aec9573441399fbb3ef9a..3c45a188b701ab0c406481146ff1942576acc413 100644 (file)
@@ -1103,8 +1103,7 @@ void kgd_gfx_v9_build_grace_period_packet_info(struct amdgpu_device *adev,
                uint32_t wait_times,
                uint32_t grace_period,
                uint32_t *reg_offset,
-               uint32_t *reg_data,
-               uint32_t inst)
+               uint32_t *reg_data)
 {
        *reg_data = wait_times;
 
@@ -1120,8 +1119,7 @@ void kgd_gfx_v9_build_grace_period_packet_info(struct amdgpu_device *adev,
                        SCH_WAVE,
                        grace_period);
 
-       *reg_offset = SOC15_REG_OFFSET(GC, GET_INST(GC, inst),
-                       mmCP_IQ_WAIT_TIME2);
+       *reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_IQ_WAIT_TIME2);
 }
 
 void kgd_gfx_v9_program_trap_handler_settings(struct amdgpu_device *adev,
index 936e501908cef3760865ed6d888127a59bbffcbc..ce424615f59b5bc753c54b8dc83bf1161fca407e 100644 (file)
@@ -100,5 +100,4 @@ void kgd_gfx_v9_build_grace_period_packet_info(struct amdgpu_device *adev,
                                               uint32_t wait_times,
                                               uint32_t grace_period,
                                               uint32_t *reg_offset,
-                                              uint32_t *reg_data,
-                                              uint32_t inst);
+                                              uint32_t *reg_data);
index 73ee14f7a9a4b83cfea610dbf8427adaa7da8b40..dce9e7d5e4ec672827f574fb64816ca205ef96ee 100644 (file)
@@ -1776,7 +1776,7 @@ static ssize_t amdgpu_atombios_get_vbios_version(struct device *dev,
        struct amdgpu_device *adev = drm_to_adev(ddev);
        struct atom_context *ctx = adev->mode_info.atom_context;
 
-       return sysfs_emit(buf, "%s\n", ctx->vbios_ver_str);
+       return sysfs_emit(buf, "%s\n", ctx->vbios_pn);
 }
 
 static DEVICE_ATTR(vbios_version, 0444, amdgpu_atombios_get_vbios_version,
index 3f001a50b34a6dfdf463910bfb5ff21ea4e651e8..30c4f5cca02c9f6f6f4aaffc363158ca8145c43e 100644 (file)
@@ -1244,32 +1244,6 @@ bool amdgpu_device_need_post(struct amdgpu_device *adev)
        return true;
 }
 
-/*
- * On APUs with >= 64GB white flickering has been observed w/ SG enabled.
- * Disable S/G on such systems until we have a proper fix.
- * https://gitlab.freedesktop.org/drm/amd/-/issues/2354
- * https://gitlab.freedesktop.org/drm/amd/-/issues/2735
- */
-bool amdgpu_sg_display_supported(struct amdgpu_device *adev)
-{
-       switch (amdgpu_sg_display) {
-       case -1:
-               break;
-       case 0:
-               return false;
-       case 1:
-               return true;
-       default:
-               return false;
-       }
-       if ((totalram_pages() << (PAGE_SHIFT - 10)) +
-           (adev->gmc.real_vram_size / 1024) >= 64000000) {
-               DRM_WARN("Disabling S/G due to >=64GB RAM\n");
-               return false;
-       }
-       return true;
-}
-
 /*
  * Intel hosts such as Raptor Lake and Sapphire Rapids don't support dynamic
  * speed switching. Until we have confirmation from Intel that a specific host
index 395c1768b9fc7d867416fca45b513f0573a19bd2..0ca95c4d4bfbe1634b270ac5afe04aec57636347 100644 (file)
@@ -43,6 +43,7 @@
 #define AMDGPU_GFX_LBPW_DISABLED_MODE          0x00000008L
 
 #define AMDGPU_MAX_GC_INSTANCES                8
+#define KGD_MAX_QUEUES                 128
 
 #define AMDGPU_MAX_GFX_QUEUES KGD_MAX_QUEUES
 #define AMDGPU_MAX_COMPUTE_QUEUES KGD_MAX_QUEUES
@@ -257,7 +258,7 @@ struct amdgpu_cu_info {
        uint32_t number;
        uint32_t ao_cu_mask;
        uint32_t ao_cu_bitmap[4][4];
-       uint32_t bitmap[4][4];
+       uint32_t bitmap[AMDGPU_MAX_GC_INSTANCES][4][4];
 };
 
 struct amdgpu_gfx_ras {
index 99f4df133ed3e8f21a77f2636e41c18a82634473..d30dc0b718c73ee8c703592b56d41c62f87d9c19 100644 (file)
@@ -839,7 +839,7 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                memcpy(&dev_info->cu_ao_bitmap[0], &adev->gfx.cu_info.ao_cu_bitmap[0],
                       sizeof(adev->gfx.cu_info.ao_cu_bitmap));
                memcpy(&dev_info->cu_bitmap[0], &adev->gfx.cu_info.bitmap[0],
-                      sizeof(adev->gfx.cu_info.bitmap));
+                      sizeof(dev_info->cu_bitmap));
                dev_info->vram_type = adev->gmc.vram_type;
                dev_info->vram_bit_width = adev->gmc.vram_width;
                dev_info->vce_harvest_config = adev->vce.harvest_config;
@@ -940,12 +940,17 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                        struct atom_context *atom_context;
 
                        atom_context = adev->mode_info.atom_context;
-                       memcpy(vbios_info.name, atom_context->name, sizeof(atom_context->name));
-                       memcpy(vbios_info.vbios_pn, atom_context->vbios_pn, sizeof(atom_context->vbios_pn));
-                       vbios_info.version = atom_context->version;
-                       memcpy(vbios_info.vbios_ver_str, atom_context->vbios_ver_str,
-                                               sizeof(atom_context->vbios_ver_str));
-                       memcpy(vbios_info.date, atom_context->date, sizeof(atom_context->date));
+                       if (atom_context) {
+                               memcpy(vbios_info.name, atom_context->name,
+                                      sizeof(atom_context->name));
+                               memcpy(vbios_info.vbios_pn, atom_context->vbios_pn,
+                                      sizeof(atom_context->vbios_pn));
+                               vbios_info.version = atom_context->version;
+                               memcpy(vbios_info.vbios_ver_str, atom_context->vbios_ver_str,
+                                      sizeof(atom_context->vbios_ver_str));
+                               memcpy(vbios_info.date, atom_context->date,
+                                      sizeof(atom_context->date));
+                       }
 
                        return copy_to_user(out, &vbios_info,
                                                min((size_t)size, sizeof(vbios_info))) ? -EFAULT : 0;
index 3c4600e15b862a826ec5d6f9423789afb112158b..163445baa4fc80a432209247e43c4fb76d4da979 100644 (file)
@@ -801,6 +801,7 @@ int amdgpu_ras_feature_enable(struct amdgpu_device *adev,
                                enable ? "enable":"disable",
                                get_ras_block_str(head),
                                amdgpu_ras_is_poison_mode_supported(adev), ret);
+                       kfree(info);
                        return ret;
                }
 
@@ -1052,7 +1053,8 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
        info->ce_count = obj->err_data.ce_count;
 
        if (err_data.ce_count) {
-               if (adev->smuio.funcs &&
+               if (!adev->aid_mask &&
+                   adev->smuio.funcs &&
                    adev->smuio.funcs->get_socket_id &&
                    adev->smuio.funcs->get_die_id) {
                        dev_info(adev->dev, "socket: %d, die: %d "
@@ -1072,7 +1074,8 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
                }
        }
        if (err_data.ue_count) {
-               if (adev->smuio.funcs &&
+               if (!adev->aid_mask &&
+                   adev->smuio.funcs &&
                    adev->smuio.funcs->get_socket_id &&
                    adev->smuio.funcs->get_die_id) {
                        dev_info(adev->dev, "socket: %d, die: %d "
index c6b4337eb20c3b38b0426fdacb95aee6c528c283..10df731998b22f873611092942008560ec67394d 100644 (file)
@@ -81,7 +81,7 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,
                     unsigned int size)
 {
        struct drm_suballoc *sa = drm_suballoc_new(&sa_manager->base, size,
-                                                  GFP_KERNEL, true, 0);
+                                                  GFP_KERNEL, false, 0);
 
        if (IS_ERR(sa)) {
                *sa_bo = NULL;
index 0aee9c8288a2b8eb88054177b52e8a8ce0404215..9032d7a24d7cd7cddfafdc494f131d9ba87a16c6 100644 (file)
@@ -9449,7 +9449,7 @@ static int gfx_v10_0_get_cu_info(struct amdgpu_device *adev,
                                gfx_v10_0_set_user_wgp_inactive_bitmap_per_sh(
                                        adev, disable_masks[i * 2 + j]);
                        bitmap = gfx_v10_0_get_cu_active_bitmap_per_sh(adev);
-                       cu_info->bitmap[i][j] = bitmap;
+                       cu_info->bitmap[0][i][j] = bitmap;
 
                        for (k = 0; k < adev->gfx.config.max_cu_per_sh; k++) {
                                if (bitmap & mask) {
index 5c3db694afa87a99382f68044b798d401d0dda5e..762d7a19f1be163fa2cbf83bd5271a32cbc043a1 100644 (file)
@@ -6368,7 +6368,7 @@ static int gfx_v11_0_get_cu_info(struct amdgpu_device *adev,
                         *    SE6: {SH0,SH1} --> {bitmap[2][2], bitmap[2][3]}
                         *    SE7: {SH0,SH1} --> {bitmap[3][2], bitmap[3][3]}
                         */
-                       cu_info->bitmap[i % 4][j + (i / 4) * 2] = bitmap;
+                       cu_info->bitmap[0][i % 4][j + (i / 4) * 2] = bitmap;
 
                        for (k = 0; k < adev->gfx.config.max_cu_per_sh; k++) {
                                if (bitmap & mask)
index da6caff78c22be23ba918c49f4334c97236c0104..34f9211b26793ff705aef4ab75e926dfba1f1dbb 100644 (file)
@@ -3577,7 +3577,7 @@ static void gfx_v6_0_get_cu_info(struct amdgpu_device *adev)
                                gfx_v6_0_set_user_cu_inactive_bitmap(
                                        adev, disable_masks[i * 2 + j]);
                        bitmap = gfx_v6_0_get_cu_enabled(adev);
-                       cu_info->bitmap[i][j] = bitmap;
+                       cu_info->bitmap[0][i][j] = bitmap;
 
                        for (k = 0; k < adev->gfx.config.max_cu_per_sh; k++) {
                                if (bitmap & mask) {
index 90b034b173c1cc9385c4668eb478c93e88b93ed1..c2faf6b4c2fced463cc24598cf10c9775a9663ee 100644 (file)
@@ -5119,7 +5119,7 @@ static void gfx_v7_0_get_cu_info(struct amdgpu_device *adev)
                                gfx_v7_0_set_user_cu_inactive_bitmap(
                                        adev, disable_masks[i * 2 + j]);
                        bitmap = gfx_v7_0_get_cu_active_bitmap(adev);
-                       cu_info->bitmap[i][j] = bitmap;
+                       cu_info->bitmap[0][i][j] = bitmap;
 
                        for (k = 0; k < adev->gfx.config.max_cu_per_sh; k++) {
                                if (bitmap & mask) {
index 51c1745c83697b04a7eab230f5a64847fceabed3..885ebd703260f05a92aa15928910e171112b2cc7 100644 (file)
@@ -7121,7 +7121,7 @@ static void gfx_v8_0_get_cu_info(struct amdgpu_device *adev)
                                gfx_v8_0_set_user_cu_inactive_bitmap(
                                        adev, disable_masks[i * 2 + j]);
                        bitmap = gfx_v8_0_get_cu_active_bitmap(adev);
-                       cu_info->bitmap[i][j] = bitmap;
+                       cu_info->bitmap[0][i][j] = bitmap;
 
                        for (k = 0; k < adev->gfx.config.max_cu_per_sh; k ++) {
                                if (bitmap & mask) {
index 458faf657042e3d6a2b8af49b508db2867bf3295..fd61574a737cb17cd843ea4b81c0c10b0f0b1661 100644 (file)
@@ -1499,7 +1499,7 @@ static void gfx_v9_0_init_always_on_cu_mask(struct amdgpu_device *adev)
                        amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff, 0);
 
                        for (k = 0; k < adev->gfx.config.max_cu_per_sh; k ++) {
-                               if (cu_info->bitmap[i][j] & mask) {
+                               if (cu_info->bitmap[0][i][j] & mask) {
                                        if (counter == pg_always_on_cu_num)
                                                WREG32_SOC15(GC, 0, mmRLC_PG_ALWAYS_ON_CU_MASK, cu_bitmap);
                                        if (counter < always_on_cu_num)
@@ -7233,7 +7233,7 @@ static int gfx_v9_0_get_cu_info(struct amdgpu_device *adev,
                         *    SE6,SH0 --> bitmap[2][1]
                         *    SE7,SH0 --> bitmap[3][1]
                         */
-                       cu_info->bitmap[i % 4][j + i / 4] = bitmap;
+                       cu_info->bitmap[0][i % 4][j + i / 4] = bitmap;
 
                        for (k = 0; k < adev->gfx.config.max_cu_per_sh; k ++) {
                                if (bitmap & mask) {
index 0a26a00074a63161d677783b1ee3f3a1c44aeed2..18ce5fe45f6f863ac33e51e8eaa019025baf82a2 100644 (file)
@@ -4259,7 +4259,7 @@ static void gfx_v9_4_3_set_gds_init(struct amdgpu_device *adev)
 }
 
 static void gfx_v9_4_3_set_user_cu_inactive_bitmap(struct amdgpu_device *adev,
-                                                u32 bitmap)
+                                                u32 bitmap, int xcc_id)
 {
        u32 data;
 
@@ -4269,15 +4269,15 @@ static void gfx_v9_4_3_set_user_cu_inactive_bitmap(struct amdgpu_device *adev,
        data = bitmap << GC_USER_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT;
        data &= GC_USER_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK;
 
-       WREG32_SOC15(GC, GET_INST(GC, 0), regGC_USER_SHADER_ARRAY_CONFIG, data);
+       WREG32_SOC15(GC, GET_INST(GC, xcc_id), regGC_USER_SHADER_ARRAY_CONFIG, data);
 }
 
-static u32 gfx_v9_4_3_get_cu_active_bitmap(struct amdgpu_device *adev)
+static u32 gfx_v9_4_3_get_cu_active_bitmap(struct amdgpu_device *adev, int xcc_id)
 {
        u32 data, mask;
 
-       data = RREG32_SOC15(GC, GET_INST(GC, 0), regCC_GC_SHADER_ARRAY_CONFIG);
-       data |= RREG32_SOC15(GC, GET_INST(GC, 0), regGC_USER_SHADER_ARRAY_CONFIG);
+       data = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCC_GC_SHADER_ARRAY_CONFIG);
+       data |= RREG32_SOC15(GC, GET_INST(GC, xcc_id), regGC_USER_SHADER_ARRAY_CONFIG);
 
        data &= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK;
        data >>= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT;
@@ -4290,7 +4290,7 @@ static u32 gfx_v9_4_3_get_cu_active_bitmap(struct amdgpu_device *adev)
 static int gfx_v9_4_3_get_cu_info(struct amdgpu_device *adev,
                                 struct amdgpu_cu_info *cu_info)
 {
-       int i, j, k, counter, active_cu_number = 0;
+       int i, j, k, counter, xcc_id, active_cu_number = 0;
        u32 mask, bitmap, ao_bitmap, ao_cu_mask = 0;
        unsigned disable_masks[4 * 4];
 
@@ -4309,46 +4309,38 @@ static int gfx_v9_4_3_get_cu_info(struct amdgpu_device *adev,
                                    adev->gfx.config.max_sh_per_se);
 
        mutex_lock(&adev->grbm_idx_mutex);
-       for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
-               for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
-                       mask = 1;
-                       ao_bitmap = 0;
-                       counter = 0;
-                       gfx_v9_4_3_xcc_select_se_sh(adev, i, j, 0xffffffff, 0);
-                       gfx_v9_4_3_set_user_cu_inactive_bitmap(
-                               adev, disable_masks[i * adev->gfx.config.max_sh_per_se + j]);
-                       bitmap = gfx_v9_4_3_get_cu_active_bitmap(adev);
-
-                       /*
-                        * The bitmap(and ao_cu_bitmap) in cu_info structure is
-                        * 4x4 size array, and it's usually suitable for Vega
-                        * ASICs which has 4*2 SE/SH layout.
-                        * But for Arcturus, SE/SH layout is changed to 8*1.
-                        * To mostly reduce the impact, we make it compatible
-                        * with current bitmap array as below:
-                        *    SE4,SH0 --> bitmap[0][1]
-                        *    SE5,SH0 --> bitmap[1][1]
-                        *    SE6,SH0 --> bitmap[2][1]
-                        *    SE7,SH0 --> bitmap[3][1]
-                        */
-                       cu_info->bitmap[i % 4][j + i / 4] = bitmap;
-
-                       for (k = 0; k < adev->gfx.config.max_cu_per_sh; k++) {
-                               if (bitmap & mask) {
-                                       if (counter < adev->gfx.config.max_cu_per_sh)
-                                               ao_bitmap |= mask;
-                                       counter++;
+       for (xcc_id = 0; xcc_id < NUM_XCC(adev->gfx.xcc_mask); xcc_id++) {
+               for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
+                       for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
+                               mask = 1;
+                               ao_bitmap = 0;
+                               counter = 0;
+                               gfx_v9_4_3_xcc_select_se_sh(adev, i, j, 0xffffffff, xcc_id);
+                               gfx_v9_4_3_set_user_cu_inactive_bitmap(
+                                       adev,
+                                       disable_masks[i * adev->gfx.config.max_sh_per_se + j],
+                                       xcc_id);
+                               bitmap = gfx_v9_4_3_get_cu_active_bitmap(adev, xcc_id);
+
+                               cu_info->bitmap[xcc_id][i][j] = bitmap;
+
+                               for (k = 0; k < adev->gfx.config.max_cu_per_sh; k++) {
+                                       if (bitmap & mask) {
+                                               if (counter < adev->gfx.config.max_cu_per_sh)
+                                                       ao_bitmap |= mask;
+                                               counter++;
+                                       }
+                                       mask <<= 1;
                                }
-                               mask <<= 1;
+                               active_cu_number += counter;
+                               if (i < 2 && j < 2)
+                                       ao_cu_mask |= (ao_bitmap << (i * 16 + j * 8));
+                               cu_info->ao_cu_bitmap[i][j] = ao_bitmap;
                        }
-                       active_cu_number += counter;
-                       if (i < 2 && j < 2)
-                               ao_cu_mask |= (ao_bitmap << (i * 16 + j * 8));
-                       cu_info->ao_cu_bitmap[i % 4][j + i / 4] = ao_bitmap;
                }
+               gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff,
+                                           xcc_id);
        }
-       gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff,
-                                   0);
        mutex_unlock(&adev->grbm_idx_mutex);
 
        cu_info->number = active_cu_number;
index d5ed9e0e1a5f157fd90bcb0bd429041cb3d3eeb2..e5b5b0f4940f4cb517e0bd6b3de4067e73426218 100644 (file)
@@ -345,6 +345,9 @@ static void nbio_v4_3_init_registers(struct amdgpu_device *adev)
                data &= ~RCC_DEV0_EPF2_STRAP2__STRAP_NO_SOFT_RESET_DEV0_F2_MASK;
                WREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF2_STRAP2, data);
        }
+       if (amdgpu_sriov_vf(adev))
+               adev->rmmio_remap.reg_offset = SOC15_REG_OFFSET(NBIO, 0,
+                       regBIF_BX_DEV0_EPF0_VF0_HDP_MEM_COHERENCY_FLUSH_CNTL) << 2;
 }
 
 static u32 nbio_v4_3_get_rom_offset(struct amdgpu_device *adev)
index 40d23738ee4ec0528fb7a13e3978654e055233ea..8b2ff2b281b0ade2f37d309476f20eb8a10c732a 100644 (file)
@@ -766,7 +766,7 @@ static int soc21_common_hw_init(void *handle)
         * for the purpose of expose those registers
         * to process space
         */
-       if (adev->nbio.funcs->remap_hdp_registers)
+       if (adev->nbio.funcs->remap_hdp_registers && !amdgpu_sriov_vf(adev))
                adev->nbio.funcs->remap_hdp_registers(adev);
        /* enable the doorbell aperture */
        adev->nbio.funcs->enable_doorbell_aperture(adev, true);
index 86fb7ac7982a1d633d83eeec8e6fde1065a02b35..f76b7aee5c0a12b9a65ccba84e573b0078c0d2fd 100644 (file)
@@ -2087,7 +2087,8 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
 
        amdgpu_amdkfd_get_cu_info(kdev->adev, &cu_info);
        cu->num_simd_per_cu = cu_info.simd_per_cu;
-       cu->num_simd_cores = cu_info.simd_per_cu * cu_info.cu_active_number;
+       cu->num_simd_cores = cu_info.simd_per_cu *
+                       (cu_info.cu_active_number / kdev->kfd->num_nodes);
        cu->max_waves_simd = cu_info.max_waves_per_simd;
 
        cu->wave_front_size = cu_info.wave_front_size;
index 387a8ef493855adbfe8718858d1ff876cc487613..74c2d7a0d6285715339482b975f946779def8e58 100644 (file)
@@ -79,6 +79,10 @@ struct crat_header {
 #define CRAT_SUBTYPE_IOLINK_AFFINITY           5
 #define CRAT_SUBTYPE_MAX                       6
 
+/*
+ * Do not change the value of CRAT_SIBLINGMAP_SIZE from 32
+ * as it breaks the ABI.
+ */
 #define CRAT_SIBLINGMAP_SIZE   32
 
 /*
index b166f30f083e0aad6498bd96f603dcfad3977296..0d3d538b64ebc319d705bcdde28ab9179c3575b4 100644 (file)
@@ -216,7 +216,7 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
 
        if (q->wptr_bo) {
                wptr_addr_off = (uint64_t)q->properties.write_ptr & (PAGE_SIZE - 1);
-               queue_input.wptr_mc_addr = ((uint64_t)q->wptr_bo->tbo.resource->start << PAGE_SHIFT) + wptr_addr_off;
+               queue_input.wptr_mc_addr = amdgpu_bo_gpu_offset(q->wptr_bo) + wptr_addr_off;
        }
 
        queue_input.is_kfd_process = 1;
@@ -1677,8 +1677,7 @@ static int start_cpsch(struct device_queue_manager *dqm)
                        dqm->dev->kfd2kgd->build_grace_period_packet_info(
                                        dqm->dev->adev, dqm->wait_times,
                                        grace_period, &reg_offset,
-                                       &dqm->wait_times,
-                                       ffs(dqm->dev->xcc_mask) - 1);
+                                       &dqm->wait_times);
        }
 
        dqm_unlock(dqm);
index c2e0b79dcc6dabe598fa023a2afba8cbcb9f0b87..7b38537c7c99bdb401ea4666d907c23253ef089e 100644 (file)
@@ -162,6 +162,7 @@ void __iomem *kfd_get_kernel_doorbell(struct kfd_dev *kfd,
                return NULL;
 
        *doorbell_off = amdgpu_doorbell_index_on_bar(kfd->adev, kfd->doorbells, inx);
+       inx *= 2;
 
        pr_debug("Get kernel queue doorbell\n"
                        "     doorbell offset   == 0x%08X\n"
@@ -176,6 +177,7 @@ void kfd_release_kernel_doorbell(struct kfd_dev *kfd, u32 __iomem *db_addr)
        unsigned int inx;
 
        inx = (unsigned int)(db_addr - kfd->doorbell_kernel_ptr);
+       inx /= 2;
 
        mutex_lock(&kfd->doorbell_mutex);
        __clear_bit(inx, kfd->doorbell_bitmap);
index d01bb57733b368c4ed692c873027352b3aa865a3..447829c22295c6cf6c7570a592c0ef33ba0211c8 100644 (file)
@@ -97,18 +97,22 @@ void free_mqd_hiq_sdma(struct mqd_manager *mm, void *mqd,
 
 void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm,
                const uint32_t *cu_mask, uint32_t cu_mask_count,
-               uint32_t *se_mask)
+               uint32_t *se_mask, uint32_t inst)
 {
        struct kfd_cu_info cu_info;
        uint32_t cu_per_sh[KFD_MAX_NUM_SE][KFD_MAX_NUM_SH_PER_SE] = {0};
        bool wgp_mode_req = KFD_GC_VERSION(mm->dev) >= IP_VERSION(10, 0, 0);
        uint32_t en_mask = wgp_mode_req ? 0x3 : 0x1;
-       int i, se, sh, cu, cu_bitmap_sh_mul, inc = wgp_mode_req ? 2 : 1;
+       int i, se, sh, cu, cu_bitmap_sh_mul, cu_inc = wgp_mode_req ? 2 : 1;
+       uint32_t cu_active_per_node;
+       int inc = cu_inc * NUM_XCC(mm->dev->xcc_mask);
+       int xcc_inst = inst + ffs(mm->dev->xcc_mask) - 1;
 
        amdgpu_amdkfd_get_cu_info(mm->dev->adev, &cu_info);
 
-       if (cu_mask_count > cu_info.cu_active_number)
-               cu_mask_count = cu_info.cu_active_number;
+       cu_active_per_node = cu_info.cu_active_number / mm->dev->kfd->num_nodes;
+       if (cu_mask_count > cu_active_per_node)
+               cu_mask_count = cu_active_per_node;
 
        /* Exceeding these bounds corrupts the stack and indicates a coding error.
         * Returning with no CU's enabled will hang the queue, which should be
@@ -141,7 +145,8 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm,
        for (se = 0; se < cu_info.num_shader_engines; se++)
                for (sh = 0; sh < cu_info.num_shader_arrays_per_engine; sh++)
                        cu_per_sh[se][sh] = hweight32(
-                               cu_info.cu_bitmap[se % 4][sh + (se / 4) * cu_bitmap_sh_mul]);
+                               cu_info.cu_bitmap[xcc_inst][se % 4][sh + (se / 4) *
+                               cu_bitmap_sh_mul]);
 
        /* Symmetrically map cu_mask to all SEs & SHs:
         * se_mask programs up to 2 SH in the upper and lower 16 bits.
@@ -164,20 +169,33 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm,
         * cu_mask[0] bit8 -> se_mask[0] bit1 (SE0,SH0,CU1)
         * ...
         *
+        * For GFX 9.4.3, the following code only looks at a
+        * subset of the cu_mask corresponding to the inst parameter.
+        * If we have n XCCs under one GPU node
+        * cu_mask[0] bit0 -> XCC0 se_mask[0] bit0 (XCC0,SE0,SH0,CU0)
+        * cu_mask[0] bit1 -> XCC1 se_mask[0] bit0 (XCC1,SE0,SH0,CU0)
+        * ..
+        * cu_mask[0] bitn -> XCCn se_mask[0] bit0 (XCCn,SE0,SH0,CU0)
+        * cu_mask[0] bit n+1 -> XCC0 se_mask[1] bit0 (XCC0,SE1,SH0,CU0)
+        *
+        * For example, if there are 6 XCCs under 1 KFD node, this code
+        * running for each inst, will look at the bits as:
+        * inst, inst + 6, inst + 12...
+        *
         * First ensure all CUs are disabled, then enable user specified CUs.
         */
        for (i = 0; i < cu_info.num_shader_engines; i++)
                se_mask[i] = 0;
 
-       i = 0;
-       for (cu = 0; cu < 16; cu += inc) {
+       i = inst;
+       for (cu = 0; cu < 16; cu += cu_inc) {
                for (sh = 0; sh < cu_info.num_shader_arrays_per_engine; sh++) {
                        for (se = 0; se < cu_info.num_shader_engines; se++) {
                                if (cu_per_sh[se][sh] > cu) {
                                        if (cu_mask[i / 32] & (en_mask << (i % 32)))
                                                se_mask[se] |= en_mask << (cu + sh * 16);
                                        i += inc;
-                                       if (i == cu_mask_count)
+                                       if (i >= cu_mask_count)
                                                return;
                                }
                        }
index 23158db7da035d9820b8b14007826f75f69f3cc1..57bf5e513f4d16198a6dda43f27f422e4df5f44a 100644 (file)
@@ -138,7 +138,7 @@ void free_mqd_hiq_sdma(struct mqd_manager *mm, void *mqd,
 
 void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm,
                const uint32_t *cu_mask, uint32_t cu_mask_count,
-               uint32_t *se_mask);
+               uint32_t *se_mask, uint32_t inst);
 
 int kfd_hiq_load_mqd_kiq(struct mqd_manager *mm, void *mqd,
                uint32_t pipe_id, uint32_t queue_id,
index ee1d32d957f2b1bc3757778506ed55a8264588e1..1a4a69943c714069ba5a2b314fabdd6849e74a6a 100644 (file)
@@ -52,7 +52,7 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
                return;
 
        mqd_symmetrically_map_cu_mask(mm,
-               minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask);
+               minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask, 0);
 
        m = get_mqd(mqd);
        m->compute_static_thread_mgmt_se0 = se_mask[0];
index 83699392c8089cd12d8bafa274c72e6e0d8bcca3..8b7fed91352696cf2b5cafab0680ad0737fa95ee 100644 (file)
@@ -52,7 +52,7 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
                return;
 
        mqd_symmetrically_map_cu_mask(mm,
-               minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask);
+               minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask, 0);
 
        m = get_mqd(mqd);
        m->compute_static_thread_mgmt_se0 = se_mask[0];
index 0bbf0edbabd47ecb9cb551173862183a7c194b76..15277f1d5cf0a9d9eb694ccaeec540e467ab774a 100644 (file)
@@ -71,7 +71,7 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
        }
 
        mqd_symmetrically_map_cu_mask(mm,
-               minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask);
+               minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask, 0);
 
        m->compute_static_thread_mgmt_se0 = se_mask[0];
        m->compute_static_thread_mgmt_se1 = se_mask[1];
@@ -321,6 +321,43 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd,
        return 0;
 }
 
+static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, void *ctl_stack_dst)
+{
+       struct v11_compute_mqd *m;
+
+       m = get_mqd(mqd);
+
+       memcpy(mqd_dst, m, sizeof(struct v11_compute_mqd));
+}
+
+static void restore_mqd(struct mqd_manager *mm, void **mqd,
+                       struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
+                       struct queue_properties *qp,
+                       const void *mqd_src,
+                       const void *ctl_stack_src, const u32 ctl_stack_size)
+{
+       uint64_t addr;
+       struct v11_compute_mqd *m;
+
+       m = (struct v11_compute_mqd *) mqd_mem_obj->cpu_ptr;
+       addr = mqd_mem_obj->gpu_addr;
+
+       memcpy(m, mqd_src, sizeof(*m));
+
+       *mqd = m;
+       if (gart_addr)
+               *gart_addr = addr;
+
+       m->cp_hqd_pq_doorbell_control =
+               qp->doorbell_off <<
+                       CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT;
+       pr_debug("cp_hqd_pq_doorbell_control 0x%x\n",
+                       m->cp_hqd_pq_doorbell_control);
+
+       qp->is_active = 0;
+}
+
+
 static void init_mqd_hiq(struct mqd_manager *mm, void **mqd,
                        struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
                        struct queue_properties *q)
@@ -458,6 +495,8 @@ struct mqd_manager *mqd_manager_init_v11(enum KFD_MQD_TYPE type,
                mqd->mqd_size = sizeof(struct v11_compute_mqd);
                mqd->get_wave_state = get_wave_state;
                mqd->mqd_stride = kfd_mqd_stride;
+               mqd->checkpoint_mqd = checkpoint_mqd;
+               mqd->restore_mqd = restore_mqd;
 #if defined(CONFIG_DEBUG_FS)
                mqd->debugfs_show_mqd = debugfs_show_mqd;
 #endif
@@ -502,6 +541,8 @@ struct mqd_manager *mqd_manager_init_v11(enum KFD_MQD_TYPE type,
                mqd->update_mqd = update_mqd_sdma;
                mqd->destroy_mqd = kfd_destroy_mqd_sdma;
                mqd->is_occupied = kfd_is_occupied_sdma;
+               mqd->checkpoint_mqd = checkpoint_mqd;
+               mqd->restore_mqd = restore_mqd;
                mqd->mqd_size = sizeof(struct v11_sdma_mqd);
                mqd->mqd_stride = kfd_mqd_stride;
 #if defined(CONFIG_DEBUG_FS)
index e23d32f356077225f06b76008b8b75cc6ab22a87..42d881809dc70e230133674e4b12f6f68567837a 100644 (file)
@@ -60,7 +60,7 @@ static inline struct v9_sdma_mqd *get_sdma_mqd(void *mqd)
 }
 
 static void update_cu_mask(struct mqd_manager *mm, void *mqd,
-                       struct mqd_update_info *minfo)
+                       struct mqd_update_info *minfo, uint32_t inst)
 {
        struct v9_mqd *m;
        uint32_t se_mask[KFD_MAX_NUM_SE] = {0};
@@ -69,27 +69,36 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
                return;
 
        mqd_symmetrically_map_cu_mask(mm,
-               minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask);
+               minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask, inst);
 
        m = get_mqd(mqd);
+
        m->compute_static_thread_mgmt_se0 = se_mask[0];
        m->compute_static_thread_mgmt_se1 = se_mask[1];
        m->compute_static_thread_mgmt_se2 = se_mask[2];
        m->compute_static_thread_mgmt_se3 = se_mask[3];
-       m->compute_static_thread_mgmt_se4 = se_mask[4];
-       m->compute_static_thread_mgmt_se5 = se_mask[5];
-       m->compute_static_thread_mgmt_se6 = se_mask[6];
-       m->compute_static_thread_mgmt_se7 = se_mask[7];
-
-       pr_debug("update cu mask to %#x %#x %#x %#x %#x %#x %#x %#x\n",
-               m->compute_static_thread_mgmt_se0,
-               m->compute_static_thread_mgmt_se1,
-               m->compute_static_thread_mgmt_se2,
-               m->compute_static_thread_mgmt_se3,
-               m->compute_static_thread_mgmt_se4,
-               m->compute_static_thread_mgmt_se5,
-               m->compute_static_thread_mgmt_se6,
-               m->compute_static_thread_mgmt_se7);
+       if (KFD_GC_VERSION(mm->dev) != IP_VERSION(9, 4, 3)) {
+               m->compute_static_thread_mgmt_se4 = se_mask[4];
+               m->compute_static_thread_mgmt_se5 = se_mask[5];
+               m->compute_static_thread_mgmt_se6 = se_mask[6];
+               m->compute_static_thread_mgmt_se7 = se_mask[7];
+
+               pr_debug("update cu mask to %#x %#x %#x %#x %#x %#x %#x %#x\n",
+                       m->compute_static_thread_mgmt_se0,
+                       m->compute_static_thread_mgmt_se1,
+                       m->compute_static_thread_mgmt_se2,
+                       m->compute_static_thread_mgmt_se3,
+                       m->compute_static_thread_mgmt_se4,
+                       m->compute_static_thread_mgmt_se5,
+                       m->compute_static_thread_mgmt_se6,
+                       m->compute_static_thread_mgmt_se7);
+       } else {
+               pr_debug("inst: %u, update cu mask to %#x %#x %#x %#x\n",
+                       inst, m->compute_static_thread_mgmt_se0,
+                       m->compute_static_thread_mgmt_se1,
+                       m->compute_static_thread_mgmt_se2,
+                       m->compute_static_thread_mgmt_se3);
+       }
 }
 
 static void set_priority(struct v9_mqd *m, struct queue_properties *q)
@@ -290,7 +299,8 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
        if (mm->dev->kfd->cwsr_enabled && q->ctx_save_restore_area_address)
                m->cp_hqd_ctx_save_control = 0;
 
-       update_cu_mask(mm, mqd, minfo);
+       if (KFD_GC_VERSION(mm->dev) != IP_VERSION(9, 4, 3))
+               update_cu_mask(mm, mqd, minfo, 0);
        set_priority(m, q);
 
        q->is_active = QUEUE_IS_ACTIVE(*q);
@@ -676,6 +686,8 @@ static void update_mqd_v9_4_3(struct mqd_manager *mm, void *mqd,
                m = get_mqd(mqd + size * xcc);
                update_mqd(mm, m, q, minfo);
 
+               update_cu_mask(mm, mqd, minfo, xcc);
+
                if (q->format == KFD_QUEUE_FORMAT_AQL) {
                        switch (xcc) {
                        case 0:
index 657c378229808fdfb2518203269fb81c744e53d0..3e1a574d4ea66981b9a5243211bd451def7aee94 100644 (file)
@@ -55,7 +55,7 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
                return;
 
        mqd_symmetrically_map_cu_mask(mm,
-               minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask);
+               minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask, 0);
 
        m = get_mqd(mqd);
        m->compute_static_thread_mgmt_se0 = se_mask[0];
index 8ce6f5200905164a433e04c290c7f63f6ca05f5a..1a03173e23133799d1d6be4a064a7fde0bb25923 100644 (file)
@@ -299,8 +299,7 @@ static int pm_set_grace_period_v9(struct packet_manager *pm,
                        pm->dqm->wait_times,
                        grace_period,
                        &reg_offset,
-                       &reg_data,
-                       0);
+                       &reg_data);
 
        if (grace_period == USE_DEFAULT_GRACE_PERIOD)
                reg_data = pm->dqm->wait_times;
index 3d9ce44d88da572faa590a3277063ecd0854d9bb..fa24e1852493dc8fb77b35efdb0e5768a34b172e 100644 (file)
@@ -1466,8 +1466,7 @@ void kfd_flush_tlb(struct kfd_process_device *pdd, enum TLB_FLUSH_TYPE type);
 
 static inline bool kfd_flush_tlb_after_unmap(struct kfd_dev *dev)
 {
-       return KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 3) ||
-              KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 2) ||
+       return KFD_GC_VERSION(dev) > IP_VERSION(9, 4, 2) ||
               (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 1) && dev->sdma_fw_version >= 18) ||
               KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 0);
 }
index ff98fded953499017a90b57c066570c09721e7e0..c8c75ff7cea80d3ba77dd23d16e1cea9213cc8df 100644 (file)
@@ -450,8 +450,7 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,
        sysfs_show_32bit_prop(buffer, offs, "cpu_cores_count",
                              dev->node_props.cpu_cores_count);
        sysfs_show_32bit_prop(buffer, offs, "simd_count",
-                             dev->gpu ? (dev->node_props.simd_count *
-                                         NUM_XCC(dev->gpu->xcc_mask)) : 0);
+                             dev->gpu ? dev->node_props.simd_count : 0);
        sysfs_show_32bit_prop(buffer, offs, "mem_banks_count",
                              dev->node_props.mem_banks_count);
        sysfs_show_32bit_prop(buffer, offs, "caches_count",
@@ -1597,14 +1596,17 @@ static int fill_in_l1_pcache(struct kfd_cache_properties **props_ext,
 static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext,
                                struct kfd_gpu_cache_info *pcache_info,
                                struct kfd_cu_info *cu_info,
-                               int cache_type, unsigned int cu_processor_id)
+                               int cache_type, unsigned int cu_processor_id,
+                               struct kfd_node *knode)
 {
        unsigned int cu_sibling_map_mask;
        int first_active_cu;
-       int i, j, k;
+       int i, j, k, xcc, start, end;
        struct kfd_cache_properties *pcache = NULL;
 
-       cu_sibling_map_mask = cu_info->cu_bitmap[0][0];
+       start = ffs(knode->xcc_mask) - 1;
+       end = start + NUM_XCC(knode->xcc_mask);
+       cu_sibling_map_mask = cu_info->cu_bitmap[start][0][0];
        cu_sibling_map_mask &=
                ((1 << pcache_info[cache_type].num_cu_shared) - 1);
        first_active_cu = ffs(cu_sibling_map_mask);
@@ -1639,16 +1641,18 @@ static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext,
                cu_sibling_map_mask = cu_sibling_map_mask >> (first_active_cu - 1);
                k = 0;
 
-               for (i = 0; i < cu_info->num_shader_engines; i++) {
-                       for (j = 0; j < cu_info->num_shader_arrays_per_engine; j++) {
-                               pcache->sibling_map[k] = (uint8_t)(cu_sibling_map_mask & 0xFF);
-                               pcache->sibling_map[k+1] = (uint8_t)((cu_sibling_map_mask >> 8) & 0xFF);
-                               pcache->sibling_map[k+2] = (uint8_t)((cu_sibling_map_mask >> 16) & 0xFF);
-                               pcache->sibling_map[k+3] = (uint8_t)((cu_sibling_map_mask >> 24) & 0xFF);
-                               k += 4;
-
-                               cu_sibling_map_mask = cu_info->cu_bitmap[i % 4][j + i / 4];
-                               cu_sibling_map_mask &= ((1 << pcache_info[cache_type].num_cu_shared) - 1);
+               for (xcc = start; xcc < end; xcc++) {
+                       for (i = 0; i < cu_info->num_shader_engines; i++) {
+                               for (j = 0; j < cu_info->num_shader_arrays_per_engine; j++) {
+                                       pcache->sibling_map[k] = (uint8_t)(cu_sibling_map_mask & 0xFF);
+                                       pcache->sibling_map[k+1] = (uint8_t)((cu_sibling_map_mask >> 8) & 0xFF);
+                                       pcache->sibling_map[k+2] = (uint8_t)((cu_sibling_map_mask >> 16) & 0xFF);
+                                       pcache->sibling_map[k+3] = (uint8_t)((cu_sibling_map_mask >> 24) & 0xFF);
+                                       k += 4;
+
+                                       cu_sibling_map_mask = cu_info->cu_bitmap[xcc][i % 4][j + i / 4];
+                                       cu_sibling_map_mask &= ((1 << pcache_info[cache_type].num_cu_shared) - 1);
+                               }
                        }
                }
                pcache->sibling_map_size = k;
@@ -1666,7 +1670,7 @@ static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext,
 static void kfd_fill_cache_non_crat_info(struct kfd_topology_device *dev, struct kfd_node *kdev)
 {
        struct kfd_gpu_cache_info *pcache_info = NULL;
-       int i, j, k;
+       int i, j, k, xcc, start, end;
        int ct = 0;
        unsigned int cu_processor_id;
        int ret;
@@ -1700,37 +1704,42 @@ static void kfd_fill_cache_non_crat_info(struct kfd_topology_device *dev, struct
         *                      then it will consider only one CU from
         *                      the shared unit
         */
+       start = ffs(kdev->xcc_mask) - 1;
+       end = start + NUM_XCC(kdev->xcc_mask);
+
        for (ct = 0; ct < num_of_cache_types; ct++) {
                cu_processor_id = gpu_processor_id;
                if (pcache_info[ct].cache_level == 1) {
-                       for (i = 0; i < pcu_info->num_shader_engines; i++) {
-                               for (j = 0; j < pcu_info->num_shader_arrays_per_engine; j++) {
-                                       for (k = 0; k < pcu_info->num_cu_per_sh; k += pcache_info[ct].num_cu_shared) {
+                       for (xcc = start; xcc < end; xcc++) {
+                               for (i = 0; i < pcu_info->num_shader_engines; i++) {
+                                       for (j = 0; j < pcu_info->num_shader_arrays_per_engine; j++) {
+                                               for (k = 0; k < pcu_info->num_cu_per_sh; k += pcache_info[ct].num_cu_shared) {
 
-                                               ret = fill_in_l1_pcache(&props_ext, pcache_info, pcu_info,
-                                                                               pcu_info->cu_bitmap[i % 4][j + i / 4], ct,
+                                                       ret = fill_in_l1_pcache(&props_ext, pcache_info, pcu_info,
+                                                                               pcu_info->cu_bitmap[xcc][i % 4][j + i / 4], ct,
                                                                                cu_processor_id, k);
 
-                                               if (ret < 0)
-                                                       break;
+                                                       if (ret < 0)
+                                                               break;
 
-                                               if (!ret) {
-                                                       num_of_entries++;
-                                                       list_add_tail(&props_ext->list, &dev->cache_props);
-                                               }
+                                                       if (!ret) {
+                                                               num_of_entries++;
+                                                               list_add_tail(&props_ext->list, &dev->cache_props);
+                                                       }
 
-                                               /* Move to next CU block */
-                                               num_cu_shared = ((k + pcache_info[ct].num_cu_shared) <=
-                                                       pcu_info->num_cu_per_sh) ?
-                                                       pcache_info[ct].num_cu_shared :
-                                                       (pcu_info->num_cu_per_sh - k);
-                                               cu_processor_id += num_cu_shared;
+                                                       /* Move to next CU block */
+                                                       num_cu_shared = ((k + pcache_info[ct].num_cu_shared) <=
+                                                               pcu_info->num_cu_per_sh) ?
+                                                               pcache_info[ct].num_cu_shared :
+                                                               (pcu_info->num_cu_per_sh - k);
+                                                       cu_processor_id += num_cu_shared;
+                                               }
                                        }
                                }
                        }
                } else {
                        ret = fill_in_l2_l3_pcache(&props_ext, pcache_info,
-                                                               pcu_info, ct, cu_processor_id);
+                                       pcu_info, ct, cu_processor_id, kdev);
 
                        if (ret < 0)
                                break;
index dea32a9e55060e8deb983e888290b19cdf58e2fd..27386ce9a021dad9a15fb7d9ac38deb32f36e8f3 100644 (file)
@@ -89,7 +89,7 @@ struct kfd_mem_properties {
        struct attribute        attr;
 };
 
-#define CACHE_SIBLINGMAP_SIZE 64
+#define CACHE_SIBLINGMAP_SIZE 128
 
 struct kfd_cache_properties {
        struct list_head        list;
index 88ba8b66de1f70d2ecc031d70e17cee564438dc9..868946dd7ef12602842ab389cef64a4275ff10da 100644 (file)
@@ -1274,11 +1274,15 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
 
        pt_base = amdgpu_gmc_pd_addr(adev->gart.bo);
 
-       page_table_start.high_part = (u32)(adev->gmc.gart_start >> 44) & 0xF;
-       page_table_start.low_part = (u32)(adev->gmc.gart_start >> 12);
-       page_table_end.high_part = (u32)(adev->gmc.gart_end >> 44) & 0xF;
-       page_table_end.low_part = (u32)(adev->gmc.gart_end >> 12);
-       page_table_base.high_part = upper_32_bits(pt_base) & 0xF;
+       page_table_start.high_part = upper_32_bits(adev->gmc.gart_start >>
+                                                  AMDGPU_GPU_PAGE_SHIFT);
+       page_table_start.low_part = lower_32_bits(adev->gmc.gart_start >>
+                                                 AMDGPU_GPU_PAGE_SHIFT);
+       page_table_end.high_part = upper_32_bits(adev->gmc.gart_end >>
+                                                AMDGPU_GPU_PAGE_SHIFT);
+       page_table_end.low_part = lower_32_bits(adev->gmc.gart_end >>
+                                               AMDGPU_GPU_PAGE_SHIFT);
+       page_table_base.high_part = upper_32_bits(pt_base);
        page_table_base.low_part = lower_32_bits(pt_base);
 
        pa_config->system_aperture.start_addr = (uint64_t)logical_addr_low << 18;
@@ -1640,8 +1644,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
                }
                break;
        }
-       if (init_data.flags.gpu_vm_support)
-               init_data.flags.gpu_vm_support = amdgpu_sg_display_supported(adev);
+       if (init_data.flags.gpu_vm_support &&
+           (amdgpu_sg_display == 0))
+               init_data.flags.gpu_vm_support = false;
 
        if (init_data.flags.gpu_vm_support)
                adev->mode_info.gpu_vm_support = true;
@@ -2335,14 +2340,62 @@ static int dm_late_init(void *handle)
        return detect_mst_link_for_all_connectors(adev_to_drm(adev));
 }
 
+static void resume_mst_branch_status(struct drm_dp_mst_topology_mgr *mgr)
+{
+       int ret;
+       u8 guid[16];
+       u64 tmp64;
+
+       mutex_lock(&mgr->lock);
+       if (!mgr->mst_primary)
+               goto out_fail;
+
+       if (drm_dp_read_dpcd_caps(mgr->aux, mgr->dpcd) < 0) {
+               drm_dbg_kms(mgr->dev, "dpcd read failed - undocked during suspend?\n");
+               goto out_fail;
+       }
+
+       ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
+                                DP_MST_EN |
+                                DP_UP_REQ_EN |
+                                DP_UPSTREAM_IS_SRC);
+       if (ret < 0) {
+               drm_dbg_kms(mgr->dev, "mst write failed - undocked during suspend?\n");
+               goto out_fail;
+       }
+
+       /* Some hubs forget their guids after they resume */
+       ret = drm_dp_dpcd_read(mgr->aux, DP_GUID, guid, 16);
+       if (ret != 16) {
+               drm_dbg_kms(mgr->dev, "dpcd read failed - undocked during suspend?\n");
+               goto out_fail;
+       }
+
+       if (memchr_inv(guid, 0, 16) == NULL) {
+               tmp64 = get_jiffies_64();
+               memcpy(&guid[0], &tmp64, sizeof(u64));
+               memcpy(&guid[8], &tmp64, sizeof(u64));
+
+               ret = drm_dp_dpcd_write(mgr->aux, DP_GUID, guid, 16);
+
+               if (ret != 16) {
+                       drm_dbg_kms(mgr->dev, "check mstb guid failed - undocked during suspend?\n");
+                       goto out_fail;
+               }
+       }
+
+       memcpy(mgr->mst_primary->guid, guid, 16);
+
+out_fail:
+       mutex_unlock(&mgr->lock);
+}
+
 static void s3_handle_mst(struct drm_device *dev, bool suspend)
 {
        struct amdgpu_dm_connector *aconnector;
        struct drm_connector *connector;
        struct drm_connector_list_iter iter;
        struct drm_dp_mst_topology_mgr *mgr;
-       int ret;
-       bool need_hotplug = false;
 
        drm_connector_list_iter_begin(dev, &iter);
        drm_for_each_connector_iter(connector, &iter) {
@@ -2364,18 +2417,15 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend)
                        if (!dp_is_lttpr_present(aconnector->dc_link))
                                try_to_configure_aux_timeout(aconnector->dc_link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD);
 
-                       ret = drm_dp_mst_topology_mgr_resume(mgr, true);
-                       if (ret < 0) {
-                               dm_helpers_dp_mst_stop_top_mgr(aconnector->dc_link->ctx,
-                                       aconnector->dc_link);
-                               need_hotplug = true;
-                       }
+                       /* TODO: move resume_mst_branch_status() into drm mst resume again
+                        * once topology probing work is pulled out from mst resume into mst
+                        * resume 2nd step. mst resume 2nd step should be called after old
+                        * state getting restored (i.e. drm_atomic_helper_resume()).
+                        */
+                       resume_mst_branch_status(mgr);
                }
        }
        drm_connector_list_iter_end(&iter);
-
-       if (need_hotplug)
-               drm_kms_helper_hotplug_event(dev);
 }
 
 static int amdgpu_dm_smu_write_watermarks_table(struct amdgpu_device *adev)
@@ -2769,7 +2819,8 @@ static int dm_resume(void *handle)
        struct dm_atomic_state *dm_state = to_dm_atomic_state(dm->atomic_obj.state);
        enum dc_connection_type new_connection_type = dc_connection_none;
        struct dc_state *dc_state;
-       int i, r, j;
+       int i, r, j, ret;
+       bool need_hotplug = false;
 
        if (amdgpu_in_reset(adev)) {
                dc_state = dm->cached_dc_state;
@@ -2867,7 +2918,7 @@ static int dm_resume(void *handle)
                        continue;
 
                /*
-                * this is the case when traversing through already created
+                * this is the case when traversing through already created end sink
                 * MST connectors, should be skipped
                 */
                if (aconnector && aconnector->mst_root)
@@ -2927,6 +2978,27 @@ static int dm_resume(void *handle)
 
        dm->cached_state = NULL;
 
+       /* Do mst topology probing after resuming cached state*/
+       drm_connector_list_iter_begin(ddev, &iter);
+       drm_for_each_connector_iter(connector, &iter) {
+               aconnector = to_amdgpu_dm_connector(connector);
+               if (aconnector->dc_link->type != dc_connection_mst_branch ||
+                   aconnector->mst_root)
+                       continue;
+
+               ret = drm_dp_mst_topology_mgr_resume(&aconnector->mst_mgr, true);
+
+               if (ret < 0) {
+                       dm_helpers_dp_mst_stop_top_mgr(aconnector->dc_link->ctx,
+                                       aconnector->dc_link);
+                       need_hotplug = true;
+               }
+       }
+       drm_connector_list_iter_end(&iter);
+
+       if (need_hotplug)
+               drm_kms_helper_hotplug_event(ddev);
+
        amdgpu_dm_irq_resume_late(adev);
 
        amdgpu_dm_smu_write_watermarks_table(adev);
@@ -6026,8 +6098,6 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
 
        if (recalculate_timing)
                drm_mode_set_crtcinfo(&saved_mode, 0);
-       else if (!old_stream)
-               drm_mode_set_crtcinfo(&mode, 0);
 
        /*
         * If scaling is enabled and refresh rate didn't change
@@ -6589,6 +6659,8 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec
                goto fail;
        }
 
+       drm_mode_set_crtcinfo(mode, 0);
+
        stream = create_validate_stream_for_sink(aconnector, mode,
                                                 to_dm_connector_state(connector->state),
                                                 NULL);
@@ -8073,7 +8145,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                bundle->surface_updates[planes_count].plane_info =
                        &bundle->plane_infos[planes_count];
 
-               if (acrtc_state->stream->link->psr_settings.psr_feature_enabled) {
+               if (acrtc_state->stream->link->psr_settings.psr_feature_enabled ||
+                   acrtc_state->stream->link->replay_settings.replay_feature_enabled) {
                        fill_dc_dirty_rects(plane, old_plane_state,
                                            new_plane_state, new_crtc_state,
                                            &bundle->flip_addrs[planes_count],
index a2d34be82613c5614f1b6cecb3f987121ae0afd0..9e4cc5eeda767e36bd591dff20adf2202dd93119 100644 (file)
@@ -620,7 +620,7 @@ struct amdgpu_hdmi_vsdb_info {
        unsigned int max_refresh_rate_hz;
 
        /**
-        * @replay mode: Replay supported
+        * @replay_mode: Replay supported
         */
        bool replay_mode;
 };
index 30c0644d4418fb418ebdbde8f49e503469125732..be5a6d008b290db14ba043feb2b7ad5c428d49df 100644 (file)
@@ -169,11 +169,23 @@ static void add_link_enc_assignment(
 /* Return first available DIG link encoder. */
 static enum engine_id find_first_avail_link_enc(
                const struct dc_context *ctx,
-               const struct dc_state *state)
+               const struct dc_state *state,
+               enum engine_id eng_id_requested)
 {
        enum engine_id eng_id = ENGINE_ID_UNKNOWN;
        int i;
 
+       if (eng_id_requested != ENGINE_ID_UNKNOWN) {
+
+               for (i = 0; i < ctx->dc->res_pool->res_cap->num_dig_link_enc; i++) {
+                       eng_id = state->res_ctx.link_enc_cfg_ctx.link_enc_avail[i];
+                       if (eng_id == eng_id_requested)
+                               return eng_id;
+               }
+       }
+
+       eng_id = ENGINE_ID_UNKNOWN;
+
        for (i = 0; i < ctx->dc->res_pool->res_cap->num_dig_link_enc; i++) {
                eng_id = state->res_ctx.link_enc_cfg_ctx.link_enc_avail[i];
                if (eng_id != ENGINE_ID_UNKNOWN)
@@ -287,7 +299,7 @@ void link_enc_cfg_link_encs_assign(
                struct dc_stream_state *streams[],
                uint8_t stream_count)
 {
-       enum engine_id eng_id = ENGINE_ID_UNKNOWN;
+       enum engine_id eng_id = ENGINE_ID_UNKNOWN, eng_id_req = ENGINE_ID_UNKNOWN;
        int i;
        int j;
 
@@ -377,8 +389,14 @@ void link_enc_cfg_link_encs_assign(
                 * assigned to that endpoint.
                 */
                link_enc = get_link_enc_used_by_link(state, stream->link);
-               if (link_enc == NULL)
-                       eng_id = find_first_avail_link_enc(stream->ctx, state);
+               if (link_enc == NULL) {
+
+                       if (stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA &&
+                                       stream->link->dpia_preferred_eng_id != ENGINE_ID_UNKNOWN)
+                               eng_id_req = stream->link->dpia_preferred_eng_id;
+
+                       eng_id = find_first_avail_link_enc(stream->ctx, state, eng_id_req);
+               }
                else
                        eng_id =  link_enc->preferred_engine;
 
@@ -402,7 +420,9 @@ void link_enc_cfg_link_encs_assign(
                        DC_LOG_DEBUG("%s: CUR %s(%d) - enc_id(%d)\n",
                                        __func__,
                                        assignment.ep_id.ep_type == DISPLAY_ENDPOINT_PHY ? "PHY" : "DPIA",
-                                       assignment.ep_id.link_id.enum_id - 1,
+                                       assignment.ep_id.ep_type == DISPLAY_ENDPOINT_PHY ?
+                                                       assignment.ep_id.link_id.enum_id :
+                                                       assignment.ep_id.link_id.enum_id - 1,
                                        assignment.eng_id);
        }
        for (i = 0; i < MAX_PIPES; i++) {
@@ -413,7 +433,9 @@ void link_enc_cfg_link_encs_assign(
                        DC_LOG_DEBUG("%s: NEW %s(%d) - enc_id(%d)\n",
                                        __func__,
                                        assignment.ep_id.ep_type == DISPLAY_ENDPOINT_PHY ? "PHY" : "DPIA",
-                                       assignment.ep_id.link_id.enum_id - 1,
+                                       assignment.ep_id.ep_type == DISPLAY_ENDPOINT_PHY ?
+                                                       assignment.ep_id.link_id.enum_id :
+                                                       assignment.ep_id.link_id.enum_id - 1,
                                        assignment.eng_id);
        }
 
@@ -478,7 +500,6 @@ struct dc_link *link_enc_cfg_get_link_using_link_enc(
        if (stream)
                link = stream->link;
 
-       // dm_output_to_console("%s: No link using DIG(%d).\n", __func__, eng_id);
        return link;
 }
 
index 0d0bef8eb331d8f35ca0978e0615e187a5198431..31e3183497a7f50a1e141286b1183f3ad76909a5 100644 (file)
@@ -1496,6 +1496,7 @@ struct dc_link {
         * object creation.
         */
        enum engine_id eng_id;
+       enum engine_id dpia_preferred_eng_id;
 
        bool test_pattern_enabled;
        enum dp_test_pattern current_test_pattern;
index ad967b58d7bec6ee727b6209767df3bd87c55300..2a6157555fd1e4617c4f7320c49b367eab1d543f 100644 (file)
@@ -964,7 +964,9 @@ void dce110_edp_backlight_control(
                return;
        }
 
-       if (link->panel_cntl) {
+       if (link->panel_cntl && !(link->dpcd_sink_ext_caps.bits.oled ||
+               link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 ||
+               link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1)) {
                bool is_backlight_on = link->panel_cntl->funcs->is_panel_backlight_on(link->panel_cntl);
 
                if ((enable && is_backlight_on) || (!enable && !is_backlight_on)) {
@@ -1176,12 +1178,15 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
                dto_params.otg_inst = tg->inst;
                dto_params.timing = &pipe_ctx->stream->timing;
                dp_hpo_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst;
-               dccg->funcs->set_dtbclk_dto(dccg, &dto_params);
-               dccg->funcs->disable_symclk32_se(dccg, dp_hpo_inst);
-               dccg->funcs->set_dpstreamclk(dccg, REFCLK, tg->inst, dp_hpo_inst);
-       } else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST && dccg->funcs->disable_symclk_se)
+               if (dccg) {
+                       dccg->funcs->set_dtbclk_dto(dccg, &dto_params);
+                       dccg->funcs->disable_symclk32_se(dccg, dp_hpo_inst);
+                       dccg->funcs->set_dpstreamclk(dccg, REFCLK, tg->inst, dp_hpo_inst);
+               }
+       } else if (dccg && dccg->funcs->disable_symclk_se) {
                dccg->funcs->disable_symclk_se(dccg, stream_enc->stream_enc_inst,
                                link_enc->transmitter - TRANSMITTER_UNIPHY_A);
+       }
 
        if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) {
                /* TODO: This looks like a bug to me as we are disabling HPO IO when
@@ -2656,11 +2661,11 @@ void dce110_prepare_bandwidth(
        struct clk_mgr *dccg = dc->clk_mgr;
 
        dce110_set_safe_displaymarks(&context->res_ctx, dc->res_pool);
-
-       dccg->funcs->update_clocks(
-                       dccg,
-                       context,
-                       false);
+       if (dccg)
+               dccg->funcs->update_clocks(
+                               dccg,
+                               context,
+                               false);
 }
 
 void dce110_optimize_bandwidth(
@@ -2671,10 +2676,11 @@ void dce110_optimize_bandwidth(
 
        dce110_set_displaymarks(dc, context);
 
-       dccg->funcs->update_clocks(
-                       dccg,
-                       context,
-                       true);
+       if (dccg)
+               dccg->funcs->update_clocks(
+                               dccg,
+                               context,
+                               true);
 }
 
 static void dce110_program_front_end_for_pipe(
index e72f15ac00482df19be0cdd9d9affef5f981a2d1..aeadc587433fd5a1410123b8529e60c48496a292 100644 (file)
@@ -2692,8 +2692,6 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
        struct dce_hwseq *hws = dc->hwseq;
        unsigned int k1_div = PIXEL_RATE_DIV_NA;
        unsigned int k2_div = PIXEL_RATE_DIV_NA;
-       struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link);
-       struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc;
 
        if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) {
                if (dc->hwseq->funcs.setup_hpo_hw_control)
@@ -2713,10 +2711,8 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
                dto_params.timing = &pipe_ctx->stream->timing;
                dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr);
                dccg->funcs->set_dtbclk_dto(dccg, &dto_params);
-       } else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST && dccg->funcs->enable_symclk_se)
-               dccg->funcs->enable_symclk_se(dccg,
-                       stream_enc->stream_enc_inst, link_enc->transmitter - TRANSMITTER_UNIPHY_A);
-
+       } else {
+               }
        if (hws->funcs.calculate_dccg_k1_k2_values && dc->res_pool->dccg->funcs->set_pixel_rate_div) {
                hws->funcs.calculate_dccg_k1_k2_values(pipe_ctx, &k1_div, &k2_div);
 
index 1c1fb2fa082296908074f93b350d64259bf9f99f..004beed9bd444c7df896f07305726f2266fd652c 100644 (file)
@@ -1032,6 +1032,28 @@ static const struct dce_i2c_mask i2c_masks = {
                I2C_COMMON_MASK_SH_LIST_DCN30(_MASK)
 };
 
+/* ========================================================== */
+
+/*
+ * DPIA index | Preferred Encoder     |    Host Router
+ *   0        |      C                |       0
+ *   1        |      First Available  |       0
+ *   2        |      D                |       1
+ *   3        |      First Available  |       1
+ */
+/* ========================================================== */
+static const enum engine_id dpia_to_preferred_enc_id_table[] = {
+               ENGINE_ID_DIGC,
+               ENGINE_ID_DIGC,
+               ENGINE_ID_DIGD,
+               ENGINE_ID_DIGD
+};
+
+static enum engine_id dcn314_get_preferred_eng_id_dpia(unsigned int dpia_index)
+{
+       return dpia_to_preferred_enc_id_table[dpia_index];
+}
+
 static struct dce_i2c_hw *dcn31_i2c_hw_create(
        struct dc_context *ctx,
        uint32_t inst)
@@ -1785,6 +1807,7 @@ static struct resource_funcs dcn314_res_pool_funcs = {
        .update_bw_bounding_box = dcn314_update_bw_bounding_box,
        .patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
        .get_panel_config_defaults = dcn314_get_panel_config_defaults,
+       .get_preferred_eng_id_dpia = dcn314_get_preferred_eng_id_dpia,
 };
 
 static struct clock_source *dcn30_clock_source_create(
index 3082da04a63db76d8b15cd7f62bf639e18f083d4..1d052f08aff5e16ffc10a9695bca927a64ea68f5 100644 (file)
@@ -75,7 +75,7 @@ void mpc32_power_on_blnd_lut(
                if (power_on) {
                        REG_UPDATE(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_1DLUT_MEM_PWR_FORCE, 0);
                        REG_WAIT(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_1DLUT_MEM_PWR_STATE, 0, 1, 5);
-               } else {
+               } else if (!mpc->ctx->dc->debug.disable_mem_low_power) {
                        ASSERT(false);
                        /* TODO: change to mpc
                         *  dpp_base->ctx->dc->optimized_required = true;
index 027aec70c070f8d566986a3222117ae7e39acb3d..eaad1260bfd1808c40bea358ed410051ef5440d8 100644 (file)
@@ -65,6 +65,7 @@ struct resource_context;
 struct clk_bw_params;
 
 struct resource_funcs {
+       enum engine_id (*get_preferred_eng_id_dpia)(unsigned int dpia_index);
        void (*destroy)(struct resource_pool **pool);
        void (*link_init)(struct dc_link *link);
        struct panel_cntl*(*panel_cntl_create)(
index 195ca9e52edaaba87a8bd679b55eb643abc044eb..0895742a3102418152eff96f2939d29d116652c0 100644 (file)
@@ -791,6 +791,10 @@ static bool construct_dpia(struct dc_link *link,
        /* Set dpia port index : 0 to number of dpia ports */
        link->ddc_hw_inst = init_params->connector_index;
 
+       // Assign Dpia preferred eng_id
+       if (link->dc->res_pool->funcs->get_preferred_eng_id_dpia)
+               link->dpia_preferred_eng_id = link->dc->res_pool->funcs->get_preferred_eng_id_dpia(link->ddc_hw_inst);
+
        /* TODO: Create link encoder */
 
        link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
index 8433f99f66679dbcee25bb7567d993fcb8673294..3b5a56585c4b7283017651aad21ed1c0565ad37f 100644 (file)
 #include <linux/types.h>
 #include <linux/bitmap.h>
 #include <linux/dma-fence.h>
+#include "amdgpu_irq.h"
+#include "amdgpu_gfx.h"
 
 struct pci_dev;
 struct amdgpu_device;
 
-#define KGD_MAX_QUEUES 128
-
 struct kfd_dev;
 struct kgd_mem;
 
@@ -68,7 +68,7 @@ struct kfd_cu_info {
        uint32_t wave_front_size;
        uint32_t max_scratch_slots_per_cu;
        uint32_t lds_size;
-       uint32_t cu_bitmap[4][4];
+       uint32_t cu_bitmap[AMDGPU_MAX_GC_INSTANCES][4][4];
 };
 
 /* For getting GPU local memory information from KGD */
@@ -326,8 +326,7 @@ struct kfd2kgd_calls {
                        uint32_t wait_times,
                        uint32_t grace_period,
                        uint32_t *reg_offset,
-                       uint32_t *reg_data,
-                       uint32_t inst);
+                       uint32_t *reg_data);
        void (*get_cu_occupancy)(struct amdgpu_device *adev, int pasid,
                        int *wave_cnt, int *max_waves_per_cu, uint32_t inst);
        void (*program_trap_handler_settings)(struct amdgpu_device *adev,
index 199a673b81201d7ad6261867bb150c5564d13958..de80e191a92c4946e3571da69268ac874e982f10 100644 (file)
@@ -336,7 +336,7 @@ static int smu_v13_0_6_setup_driver_pptable(struct smu_context *smu)
 
        /* Store one-time values in driver PPTable */
        if (!pptable->Init) {
-               while (retry--) {
+               while (--retry) {
                        ret = smu_v13_0_6_get_metrics_table(smu, NULL, true);
                        if (ret)
                                return ret;
index bf8371dc2a612111a9b2aaa40e06d3f063ba6120..c44d5bcf12847b7e130fc2ed4adf708dd55deebd 100644 (file)
@@ -2203,6 +2203,7 @@ static int drm_mode_create_colorspace_property(struct drm_connector *connector,
 /**
  * drm_mode_create_hdmi_colorspace_property - create hdmi colorspace property
  * @connector: connector to create the Colorspace property on.
+ * @supported_colorspaces: bitmap of supported color spaces
  *
  * Called by a driver the first time it's needed, must be attached to desired
  * HDMI connectors.
@@ -2227,6 +2228,7 @@ EXPORT_SYMBOL(drm_mode_create_hdmi_colorspace_property);
 /**
  * drm_mode_create_dp_colorspace_property - create dp colorspace property
  * @connector: connector to create the Colorspace property on.
+ * @supported_colorspaces: bitmap of supported color spaces
  *
  * Called by a driver the first time it's needed, must be attached to desired
  * DP connectors.
index ff69cf0fb42aab8e23ea128c81feef2883d95947..5d2809de4517cadca632e60834b52852d67a7dcd 100644 (file)
@@ -56,7 +56,7 @@ static void drm_exec_unlock_all(struct drm_exec *exec)
        struct drm_gem_object *obj;
        unsigned long index;
 
-       drm_exec_for_each_locked_object(exec, index, obj) {
+       drm_exec_for_each_locked_object_reverse(exec, index, obj) {
                dma_resv_unlock(obj->resv);
                drm_gem_object_put(obj);
        }
index 858c959f7babfffbfae06f10057f6f463a9e4ae1..f735b035436c02f0aa5a89916f6d3731752ba0a1 100644 (file)
@@ -3540,6 +3540,27 @@ enum aux_ch intel_bios_dp_aux_ch(const struct intel_bios_encoder_data *devdata)
        return map_aux_ch(devdata->i915, devdata->child.aux_channel);
 }
 
+bool intel_bios_dp_has_shared_aux_ch(const struct intel_bios_encoder_data *devdata)
+{
+       struct drm_i915_private *i915;
+       u8 aux_channel;
+       int count = 0;
+
+       if (!devdata || !devdata->child.aux_channel)
+               return false;
+
+       i915 = devdata->i915;
+       aux_channel = devdata->child.aux_channel;
+
+       list_for_each_entry(devdata, &i915->display.vbt.display_devices, node) {
+               if (intel_bios_encoder_supports_dp(devdata) &&
+                   aux_channel == devdata->child.aux_channel)
+                       count++;
+       }
+
+       return count > 1;
+}
+
 int intel_bios_dp_boost_level(const struct intel_bios_encoder_data *devdata)
 {
        if (!devdata || devdata->i915->display.vbt.version < 196 || !devdata->child.iboost)
index 9680e3e92bb516df9d42f9b5d1469010dfa1c65e..49e24b7cf6753ad2dc409ab83fc6567743170832 100644 (file)
@@ -273,6 +273,7 @@ enum aux_ch intel_bios_dp_aux_ch(const struct intel_bios_encoder_data *devdata);
 int intel_bios_dp_boost_level(const struct intel_bios_encoder_data *devdata);
 int intel_bios_dp_max_lane_count(const struct intel_bios_encoder_data *devdata);
 int intel_bios_dp_max_link_rate(const struct intel_bios_encoder_data *devdata);
+bool intel_bios_dp_has_shared_aux_ch(const struct intel_bios_encoder_data *devdata);
 int intel_bios_hdmi_boost_level(const struct intel_bios_encoder_data *devdata);
 int intel_bios_hdmi_ddc_pin(const struct intel_bios_encoder_data *devdata);
 int intel_bios_hdmi_level_shift(const struct intel_bios_encoder_data *devdata);
index 12bd2f322e6279a7b85f2ef29a8474903f18ec9d..e0e4cb529284611483afb713454bb08f617a6d40 100644 (file)
@@ -5512,8 +5512,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
        /*
         * VBT and straps are liars. Also check HPD as that seems
         * to be the most reliable piece of information available.
+        *
+        * ... expect on devices that forgot to hook HPD up for eDP
+        * (eg. Acer Chromebook C710), so we'll check it only if multiple
+        * ports are attempting to use the same AUX CH, according to VBT.
         */
-       if (!intel_digital_port_connected(encoder)) {
+       if (intel_bios_dp_has_shared_aux_ch(encoder->devdata) &&
+           !intel_digital_port_connected(encoder)) {
                /*
                 * If this fails, presume the DPCD answer came
                 * from some other port using the same AUX CH.
index ee15486fed0daa57479b07da01e2b7c3ea78391b..e85d70a62123f9bbd824c9df1542dd7ecf9c7b62 100644 (file)
@@ -558,7 +558,6 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id,
                DRIVER_CAPS(i915)->has_logical_contexts = true;
 
        ewma__engine_latency_init(&engine->latency);
-       seqcount_init(&engine->stats.execlists.lock);
 
        ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier);
 
index 8a641bcf777cb4da2c211911a470272d759314a4..3292524469d509655db5a7130a07c744af440bb3 100644 (file)
@@ -3550,6 +3550,8 @@ int intel_execlists_submission_setup(struct intel_engine_cs *engine)
        logical_ring_default_vfuncs(engine);
        logical_ring_default_irqs(engine);
 
+       seqcount_init(&engine->stats.execlists.lock);
+
        if (engine->flags & I915_ENGINE_HAS_RCS_REG_STATE)
                rcs_submission_override(engine);
 
index 957d0aeb0c022f464720f1b456192b849ebff875..c378cc7c953c47c3af190a62bcff2b36f57f9b7a 100644 (file)
@@ -1094,6 +1094,9 @@ __lrc_alloc_state(struct intel_context *ce, struct intel_engine_cs *engine)
                                          I915_BO_ALLOC_PM_VOLATILE);
        if (IS_ERR(obj)) {
                obj = i915_gem_object_create_shmem(engine->i915, context_size);
+               if (IS_ERR(obj))
+                       return ERR_CAST(obj);
+
                /*
                 * Wa_22016122933: For Media version 13.0, all Media GT shared
                 * memory needs to be mapped as WC on CPU side and UC (PAT
@@ -1102,8 +1105,6 @@ __lrc_alloc_state(struct intel_context *ce, struct intel_engine_cs *engine)
                if (intel_gt_needs_wa_22016122933(engine->gt))
                        i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE);
        }
-       if (IS_ERR(obj))
-               return ERR_CAST(obj);
 
        vma = i915_vma_instance(obj, &engine->gt->ggtt->vm, NULL);
        if (IS_ERR(vma)) {
index 9913971fa5d20bc9d192695d8b2773d0244615ce..25ea765586908f14d08715f45ca9def85a6a07f3 100644 (file)
@@ -334,6 +334,8 @@ static void meson_encoder_hdmi_hpd_notify(struct drm_bridge *bridge,
                        return;
 
                cec_notifier_set_phys_addr_from_edid(encoder_hdmi->cec_notifier, edid);
+
+               kfree(edid);
        } else
                cec_notifier_phys_addr_invalidate(encoder_hdmi->cec_notifier);
 }
index 1fe17ff95f5eec4c49e73a7123c91112c2a3fd22..e73a233c6572322dbee898b8f6962cf6b386b23f 100644 (file)
@@ -189,21 +189,12 @@ u_free(void *addr)
 static inline void *
 u_memcpya(uint64_t user, unsigned int nmemb, unsigned int size)
 {
-       void *mem;
-       void __user *userptr = (void __force __user *)(uintptr_t)user;
+       void __user *userptr = u64_to_user_ptr(user);
+       size_t bytes;
 
-       size *= nmemb;
-
-       mem = kvmalloc(size, GFP_KERNEL);
-       if (!mem)
-               return ERR_PTR(-ENOMEM);
-
-       if (copy_from_user(mem, userptr, size)) {
-               u_free(mem);
-               return ERR_PTR(-EFAULT);
-       }
-
-       return mem;
+       if (unlikely(check_mul_overflow(nmemb, size, &bytes)))
+               return ERR_PTR(-EOVERFLOW);
+       return vmemdup_user(userptr, bytes);
 }
 
 #include <nvif/object.h>
index 19024ce21fbbd968de9a26a77c59f23a7586a67b..5dda94e1318c201e6dc0003b1aaf6c600ece3f93 100644 (file)
@@ -213,7 +213,7 @@ nouveau_exec_job_timeout(struct nouveau_job *job)
 
        nouveau_sched_entity_fini(job->entity);
 
-       return DRM_GPU_SCHED_STAT_ENODEV;
+       return DRM_GPU_SCHED_STAT_NOMINAL;
 }
 
 static struct nouveau_job_ops nouveau_exec_job_ops = {
index 61d9e70da9fd536252b7643a42385717c1027957..ca762ea5541361bb023e8b0288470502797f1a15 100644 (file)
@@ -207,7 +207,7 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha
 int
 nouveau_fence_emit(struct nouveau_fence *fence)
 {
-       struct nouveau_channel *chan = fence->channel;
+       struct nouveau_channel *chan = unrcu_pointer(fence->channel);
        struct nouveau_fence_chan *fctx = chan->fence;
        struct nouveau_fence_priv *priv = (void*)chan->drm->fence;
        int ret;
index 88217185e0f388353a247a7bb033c59300f73d2f..3b7ea52212260583ffbdfae77ddd92936d1d00ae 100644 (file)
@@ -375,14 +375,20 @@ nouveau_sched_run_job(struct drm_sched_job *sched_job)
 static enum drm_gpu_sched_stat
 nouveau_sched_timedout_job(struct drm_sched_job *sched_job)
 {
+       struct drm_gpu_scheduler *sched = sched_job->sched;
        struct nouveau_job *job = to_nouveau_job(sched_job);
+       enum drm_gpu_sched_stat stat = DRM_GPU_SCHED_STAT_NOMINAL;
 
-       NV_PRINTK(warn, job->cli, "Job timed out.\n");
+       drm_sched_stop(sched, sched_job);
 
        if (job->ops->timeout)
-               return job->ops->timeout(job);
+               stat = job->ops->timeout(job);
+       else
+               NV_PRINTK(warn, job->cli, "Generic job timeout.\n");
+
+       drm_sched_start(sched, true);
 
-       return DRM_GPU_SCHED_STAT_ENODEV;
+       return stat;
 }
 
 static void
index c87a57c9c592b41cc7a1a44b23bbc8da23817862..22dd8b4456855f9b78fd3c3d32f9978be4a4ed2d 100644 (file)
@@ -123,7 +123,7 @@ int radeon_sa_bo_new(struct radeon_sa_manager *sa_manager,
                     unsigned int size, unsigned int align)
 {
        struct drm_suballoc *sa = drm_suballoc_new(&sa_manager->base, size,
-                                                  GFP_KERNEL, true, align);
+                                                  GFP_KERNEL, false, align);
 
        if (IS_ERR(sa)) {
                *sa_bo = NULL;
index 186b28dc70380f1477d5eabb49ece2e9ed37e848..05d5e7af6d250881b50b29d26e1069ca6c41273e 100644 (file)
@@ -939,7 +939,7 @@ static void drm_test_mm_insert_range(struct kunit *test)
                KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert_range(test, count, size, 0, max - 1));
                KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert_range(test, count, size, 0, max / 2));
                KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert_range(test, count, size,
-                                                                   max / 2, max / 2));
+                                                                   max / 2, max));
                KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert_range(test, count, size,
                                                                    max / 4 + 1, 3 * max / 4 - 1));
 
index c5bb683e440c5f5d8ee1ea71cf301de20e3f28c8..0187539ff5eaaa5f5c59096ed427de7f268f29e5 100644 (file)
@@ -70,10 +70,10 @@ MODULE_PARM_DESC(eco_mode, "Turn on Eco mode (less bright, more silent)");
 #define READ_STATUS_SIZE               13
 #define MISC_VALUE_SIZE                        4
 
-#define CMD_TIMEOUT                    msecs_to_jiffies(200)
-#define DATA_TIMEOUT                   msecs_to_jiffies(1000)
-#define IDLE_TIMEOUT                   msecs_to_jiffies(2000)
-#define FIRST_FRAME_TIMEOUT            msecs_to_jiffies(2000)
+#define CMD_TIMEOUT                    200
+#define DATA_TIMEOUT                   1000
+#define IDLE_TIMEOUT                   2000
+#define FIRST_FRAME_TIMEOUT            2000
 
 #define MISC_REQ_GET_SET_ECO_A         0xff
 #define MISC_REQ_GET_SET_ECO_B         0x35
@@ -389,7 +389,7 @@ static void gm12u320_fb_update_work(struct work_struct *work)
         * switches back to showing its logo.
         */
        queue_delayed_work(system_long_wq, &gm12u320->fb_update.work,
-                          IDLE_TIMEOUT);
+                          msecs_to_jiffies(IDLE_TIMEOUT));
 
        return;
 err:
index 3c00135ead45af7bd5f9b9c64236750a0cdd4ad7..5c514946bbad974cdb05ee8ee6f456066b741255 100644 (file)
@@ -361,7 +361,6 @@ static void virtio_gpu_complete_submit(struct virtio_gpu_submit *submit)
        submit->buf = NULL;
        submit->buflist = NULL;
        submit->sync_file = NULL;
-       submit->out_fence = NULL;
        submit->out_fence_fd = -1;
 }
 
index d5d4f642d3678077c7053dad9c5026e04b9f2055..3c99fb8b54e2df54ab26f8b6b15b4fd30d41183f 100644 (file)
@@ -408,15 +408,10 @@ void vkms_set_composer(struct vkms_output *out, bool enabled)
        if (enabled)
                drm_crtc_vblank_get(&out->crtc);
 
-       mutex_lock(&out->enabled_lock);
+       spin_lock_irq(&out->lock);
        old_enabled = out->composer_enabled;
        out->composer_enabled = enabled;
-
-       /* the composition wasn't enabled, so unlock the lock to make sure the lock
-        * will be balanced even if we have a failed commit
-        */
-       if (!out->composer_enabled)
-               mutex_unlock(&out->enabled_lock);
+       spin_unlock_irq(&out->lock);
 
        if (old_enabled)
                drm_crtc_vblank_put(&out->crtc);
index 3c5ebf106b66de958d78518ffecb7e6a343d9fba..61e500b8c9da2397b17fe07a98d469e25bc6d846 100644 (file)
@@ -16,7 +16,7 @@ static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer)
        struct drm_crtc *crtc = &output->crtc;
        struct vkms_crtc_state *state;
        u64 ret_overrun;
-       bool ret, fence_cookie, composer_enabled;
+       bool ret, fence_cookie;
 
        fence_cookie = dma_fence_begin_signalling();
 
@@ -25,15 +25,15 @@ static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer)
        if (ret_overrun != 1)
                pr_warn("%s: vblank timer overrun\n", __func__);
 
+       spin_lock(&output->lock);
        ret = drm_crtc_handle_vblank(crtc);
        if (!ret)
                DRM_ERROR("vkms failure on handling vblank");
 
        state = output->composer_state;
-       composer_enabled = output->composer_enabled;
-       mutex_unlock(&output->enabled_lock);
+       spin_unlock(&output->lock);
 
-       if (state && composer_enabled) {
+       if (state && output->composer_enabled) {
                u64 frame = drm_crtc_accurate_vblank_count(crtc);
 
                /* update frame_start only if a queued vkms_composer_worker()
@@ -295,7 +295,6 @@ int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
 
        spin_lock_init(&vkms_out->lock);
        spin_lock_init(&vkms_out->composer_lock);
-       mutex_init(&vkms_out->enabled_lock);
 
        vkms_out->composer_workq = alloc_ordered_workqueue("vkms_composer", 0);
        if (!vkms_out->composer_workq)
index c7ae6c2ba1df08fe903a8ff8be3782918e70efbb..8f5710debb1eb708fb9edfaf594c10382a790e66 100644 (file)
@@ -108,10 +108,8 @@ struct vkms_output {
        struct workqueue_struct *composer_workq;
        /* protects concurrent access to composer */
        spinlock_t lock;
-       /* guarantees that if the composer is enabled, a job will be queued */
-       struct mutex enabled_lock;
 
-       /* protected by @enabled_lock */
+       /* protected by @lock */
        bool composer_enabled;
        struct vkms_crtc_state *composer_state;
 
index 02a71244fc3b765d77efedcc56cbc876afdfc864..b5b81bd83bb1573d0434eeb2a6cdf54898e4f227 100644 (file)
@@ -1910,6 +1910,10 @@ static umode_t nct6775_in_is_visible(struct kobject *kobj,
        struct device *dev = kobj_to_dev(kobj);
        struct nct6775_data *data = dev_get_drvdata(dev);
        int in = index / 5;     /* voltage index */
+       int nr = index % 5;     /* attribute index */
+
+       if (nr == 1 && data->ALARM_BITS[in] == -1)
+               return 0;
 
        if (!(data->have_in & BIT(in)))
                return 0;
index c6d1a345ea6d8aee2eadc886d94287783f5c668c..9388823bb0bb960c52f0534bfad732a60778a170 100644 (file)
@@ -72,7 +72,7 @@ config I2C_MUX
 source "drivers/i2c/muxes/Kconfig"
 
 config I2C_ATR
-       tristate "I2C Address Translator (ATR) support"
+       tristate "I2C Address Translator (ATR) support" if COMPILE_TEST
        help
          Enable support for I2C Address Translator (ATR) chips.
 
index 169607e803318292b4fc071009dda41cb75e19f3..6644eebedaf3b7f4727fd88da340bd3a72314ac3 100644 (file)
@@ -1384,10 +1384,10 @@ config I2C_ICY
 
 config I2C_MLXCPLD
        tristate "Mellanox I2C driver"
-       depends on X86_64 || ARM64 || COMPILE_TEST
+       depends on X86_64 || (ARM64 && ACPI) || COMPILE_TEST
        help
          This exposes the Mellanox platform I2C busses to the linux I2C layer
-         for X86 based systems.
+         for X86 and ARM64/ACPI based systems.
          Controller is implemented as CPLD logic.
 
          This driver can also be built as a module. If so, the module will be
index 2e5acfeb76c818a3058ffbd75d59930b35e17df8..5a416b39b8183628bb71890a847b1ed3d799e806 100644 (file)
@@ -698,13 +698,16 @@ static int aspeed_i2c_master_xfer(struct i2c_adapter *adap,
 
        if (time_left == 0) {
                /*
-                * If timed out and bus is still busy in a multi master
-                * environment, attempt recovery at here.
+                * In a multi-master setup, if a timeout occurs, attempt
+                * recovery. But if the bus is idle, we still need to reset the
+                * i2c controller to clear the remaining interrupts.
                 */
                if (bus->multi_master &&
                    (readl(bus->base + ASPEED_I2C_CMD_REG) &
                     ASPEED_I2CD_BUS_BUSY_STS))
                        aspeed_i2c_recover_bus(bus);
+               else
+                       aspeed_i2c_reset(bus);
 
                /*
                 * If timed out and the state is still pending, drop the pending
index 9849f450257002e3ce41d5bbac6432646377c4ba..de3f58b60dce5d465f75e3bc509ea449f0c927d0 100644 (file)
@@ -182,6 +182,7 @@ enum cdns_i2c_slave_state {
  * @reset:             Reset control for the device
  * @quirks:            flag for broken hold bit usage in r1p10
  * @ctrl_reg:          Cached value of the control register.
+ * @rinfo:             I2C GPIO recovery information
  * @ctrl_reg_diva_divb: value of fields DIV_A and DIV_B from CR register
  * @slave:             Registered slave instance.
  * @dev_mode:          I2C operating role(master/slave).
index cdd8c67d91298681f5243f307fc77cd7a5536f15..affcfb243f0f52a5848a48016eac8e78ef709f7e 100644 (file)
@@ -441,8 +441,25 @@ err_release_lock:
 
 void __i2c_dw_disable(struct dw_i2c_dev *dev)
 {
+       unsigned int raw_intr_stats;
+       unsigned int enable;
        int timeout = 100;
+       bool abort_needed;
        unsigned int status;
+       int ret;
+
+       regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &raw_intr_stats);
+       regmap_read(dev->map, DW_IC_ENABLE, &enable);
+
+       abort_needed = raw_intr_stats & DW_IC_INTR_MST_ON_HOLD;
+       if (abort_needed) {
+               regmap_write(dev->map, DW_IC_ENABLE, enable | DW_IC_ENABLE_ABORT);
+               ret = regmap_read_poll_timeout(dev->map, DW_IC_ENABLE, enable,
+                                              !(enable & DW_IC_ENABLE_ABORT), 10,
+                                              100);
+               if (ret)
+                       dev_err(dev->dev, "timeout while trying to abort current transfer\n");
+       }
 
        do {
                __i2c_dw_disable_nowait(dev);
index cf4f684f535664ff59275d604cdbbbe7dc60939c..a7f6f3eafad7dd72241f57a2a356219d36bfaf56 100644 (file)
@@ -98,6 +98,7 @@
 #define DW_IC_INTR_START_DET                   BIT(10)
 #define DW_IC_INTR_GEN_CALL                    BIT(11)
 #define DW_IC_INTR_RESTART_DET                 BIT(12)
+#define DW_IC_INTR_MST_ON_HOLD                 BIT(13)
 
 #define DW_IC_INTR_DEFAULT_MASK                        (DW_IC_INTR_RX_FULL | \
                                                 DW_IC_INTR_TX_ABRT | \
                                                 DW_IC_INTR_RX_UNDER | \
                                                 DW_IC_INTR_RD_REQ)
 
+#define DW_IC_ENABLE_ABORT                     BIT(1)
+
 #define DW_IC_STATUS_ACTIVITY                  BIT(0)
 #define DW_IC_STATUS_TFE                       BIT(2)
 #define DW_IC_STATUS_RFNE                      BIT(3)
index 73ae064321331d9bd920299096698b1456944388..1d855258a45dc3c68c71280cb791f77383f38457 100644 (file)
@@ -1754,6 +1754,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
                "SMBus I801 adapter at %04lx", priv->smba);
        err = i2c_add_adapter(&priv->adapter);
        if (err) {
+               platform_device_unregister(priv->tco_pdev);
                i801_acpi_remove(priv);
                return err;
        }
index b3bb97762c859fcdc04c3b21491055d9f105ce4e..71391b590adaeba9d69044dd5b66afcfa8c32aea 100644 (file)
@@ -710,7 +710,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
                 * reset the IP instead of just flush fifos
                 */
                ret = xiic_reinit(i2c);
-               if (!ret)
+               if (ret < 0)
                        dev_dbg(i2c->adap.dev.parent, "reinit failed\n");
 
                if (i2c->rx_msg) {
index a3a122fae71e09853200069e668b326e139eb90f..22f2280eab7f75101a8233911f6c7dd8be3bef6c 100644 (file)
@@ -243,6 +243,10 @@ static int i2c_demux_pinctrl_probe(struct platform_device *pdev)
 
                props[i].name = devm_kstrdup(&pdev->dev, "status", GFP_KERNEL);
                props[i].value = devm_kstrdup(&pdev->dev, "ok", GFP_KERNEL);
+               if (!props[i].name || !props[i].value) {
+                       err = -ENOMEM;
+                       goto err_rollback;
+               }
                props[i].length = 3;
 
                of_changeset_init(&priv->chan[i].chgset);
index 5d5cbe0130cdf99de1917d5c013b8894c622a727..5ca03bd34c8d115190327c5d8e35d3b09d554ef9 100644 (file)
@@ -105,8 +105,10 @@ static int i2c_mux_gpio_probe_fw(struct gpiomux *mux,
 
                } else if (is_acpi_node(child)) {
                        rc = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), values + i);
-                       if (rc)
+                       if (rc) {
+                               fwnode_handle_put(child);
                                return dev_err_probe(dev, rc, "Cannot get address\n");
+                       }
                }
 
                i++;
index 0d93661f88d306e0d0aa3a1ac085880a8b63d9d6..095b9b49aa8250a1f56c531883cce5f6e8a24727 100644 (file)
@@ -214,6 +214,7 @@ struct dm_table {
 
        /* a list of devices used by this table */
        struct list_head devices;
+       struct rw_semaphore devices_lock;
 
        /* events get handed up using this callback */
        void (*event_fn)(void *data);
index f5ed729a8e0cd300cd8acfb6864ae8c289da00ad..21ebb6c39394b6298ac748ffb32d11d00ad218af 100644 (file)
@@ -1630,6 +1630,8 @@ static void retrieve_deps(struct dm_table *table,
        struct dm_dev_internal *dd;
        struct dm_target_deps *deps;
 
+       down_read(&table->devices_lock);
+
        deps = get_result_buffer(param, param_size, &len);
 
        /*
@@ -1644,7 +1646,7 @@ static void retrieve_deps(struct dm_table *table,
        needed = struct_size(deps, dev, count);
        if (len < needed) {
                param->flags |= DM_BUFFER_FULL_FLAG;
-               return;
+               goto out;
        }
 
        /*
@@ -1656,6 +1658,9 @@ static void retrieve_deps(struct dm_table *table,
                deps->dev[count++] = huge_encode_dev(dd->dm_dev->bdev->bd_dev);
 
        param->data_size = param->data_start + needed;
+
+out:
+       up_read(&table->devices_lock);
 }
 
 static int table_deps(struct file *filp, struct dm_ioctl *param, size_t param_size)
index 7d208b2b1a192d88eaaec34d5247d8f7ef6273e8..37b48f63ae6a5e40b02234f214eaff487ca35e12 100644 (file)
@@ -135,6 +135,7 @@ int dm_table_create(struct dm_table **result, blk_mode_t mode,
                return -ENOMEM;
 
        INIT_LIST_HEAD(&t->devices);
+       init_rwsem(&t->devices_lock);
 
        if (!num_targets)
                num_targets = KEYS_PER_NODE;
@@ -359,16 +360,20 @@ int __ref dm_get_device(struct dm_target *ti, const char *path, blk_mode_t mode,
        if (dev == disk_devt(t->md->disk))
                return -EINVAL;
 
+       down_write(&t->devices_lock);
+
        dd = find_device(&t->devices, dev);
        if (!dd) {
                dd = kmalloc(sizeof(*dd), GFP_KERNEL);
-               if (!dd)
-                       return -ENOMEM;
+               if (!dd) {
+                       r = -ENOMEM;
+                       goto unlock_ret_r;
+               }
 
                r = dm_get_table_device(t->md, dev, mode, &dd->dm_dev);
                if (r) {
                        kfree(dd);
-                       return r;
+                       goto unlock_ret_r;
                }
 
                refcount_set(&dd->count, 1);
@@ -378,12 +383,17 @@ int __ref dm_get_device(struct dm_target *ti, const char *path, blk_mode_t mode,
        } else if (dd->dm_dev->mode != (mode | dd->dm_dev->mode)) {
                r = upgrade_mode(dd, mode, t->md);
                if (r)
-                       return r;
+                       goto unlock_ret_r;
        }
        refcount_inc(&dd->count);
 out:
+       up_write(&t->devices_lock);
        *result = dd->dm_dev;
        return 0;
+
+unlock_ret_r:
+       up_write(&t->devices_lock);
+       return r;
 }
 EXPORT_SYMBOL(dm_get_device);
 
@@ -419,9 +429,12 @@ static int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
 void dm_put_device(struct dm_target *ti, struct dm_dev *d)
 {
        int found = 0;
-       struct list_head *devices = &ti->table->devices;
+       struct dm_table *t = ti->table;
+       struct list_head *devices = &t->devices;
        struct dm_dev_internal *dd;
 
+       down_write(&t->devices_lock);
+
        list_for_each_entry(dd, devices, list) {
                if (dd->dm_dev == d) {
                        found = 1;
@@ -430,14 +443,17 @@ void dm_put_device(struct dm_target *ti, struct dm_dev *d)
        }
        if (!found) {
                DMERR("%s: device %s not in table devices list",
-                     dm_device_name(ti->table->md), d->name);
-               return;
+                     dm_device_name(t->md), d->name);
+               goto unlock_ret;
        }
        if (refcount_dec_and_test(&dd->count)) {
-               dm_put_table_device(ti->table->md, d);
+               dm_put_table_device(t->md, d);
                list_del(&dd->list);
                kfree(dd);
        }
+
+unlock_ret:
+       up_write(&t->devices_lock);
 }
 EXPORT_SYMBOL(dm_put_device);
 
index f0f118ab20fa26371c9bd5395d3763fa34c7ff34..64a1f306c96c11eea2ac754334646dcb7c4e8586 100644 (file)
@@ -715,24 +715,6 @@ static void dm_put_live_table_fast(struct mapped_device *md) __releases(RCU)
        rcu_read_unlock();
 }
 
-static inline struct dm_table *dm_get_live_table_bio(struct mapped_device *md,
-                                       int *srcu_idx, blk_opf_t bio_opf)
-{
-       if (bio_opf & REQ_NOWAIT)
-               return dm_get_live_table_fast(md);
-       else
-               return dm_get_live_table(md, srcu_idx);
-}
-
-static inline void dm_put_live_table_bio(struct mapped_device *md, int srcu_idx,
-                                        blk_opf_t bio_opf)
-{
-       if (bio_opf & REQ_NOWAIT)
-               dm_put_live_table_fast(md);
-       else
-               dm_put_live_table(md, srcu_idx);
-}
-
 static char *_dm_claim_ptr = "I belong to device-mapper";
 
 /*
@@ -1833,9 +1815,8 @@ static void dm_submit_bio(struct bio *bio)
        struct mapped_device *md = bio->bi_bdev->bd_disk->private_data;
        int srcu_idx;
        struct dm_table *map;
-       blk_opf_t bio_opf = bio->bi_opf;
 
-       map = dm_get_live_table_bio(md, &srcu_idx, bio_opf);
+       map = dm_get_live_table(md, &srcu_idx);
 
        /* If suspended, or map not yet available, queue this IO for later */
        if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) ||
@@ -1851,7 +1832,7 @@ static void dm_submit_bio(struct bio *bio)
 
        dm_split_and_process_bio(md, map, bio);
 out:
-       dm_put_live_table_bio(md, srcu_idx, bio_opf);
+       dm_put_live_table(md, srcu_idx);
 }
 
 static bool dm_poll_dm_io(struct dm_io *io, struct io_comp_batch *iob,
index 0fe7ab6e8ab9fef50e67d63a563ef7f692c9fe63..a104a025084dc726056c42b0b1a0dd37ea774803 100644 (file)
@@ -798,14 +798,14 @@ void mddev_unlock(struct mddev *mddev)
        } else
                mutex_unlock(&mddev->reconfig_mutex);
 
+       md_wakeup_thread(mddev->thread);
+       wake_up(&mddev->sb_wait);
+
        list_for_each_entry_safe(rdev, tmp, &delete, same_set) {
                list_del_init(&rdev->same_set);
                kobject_del(&rdev->kobj);
                export_rdev(rdev, mddev);
        }
-
-       md_wakeup_thread(mddev->thread);
-       wake_up(&mddev->sb_wait);
 }
 EXPORT_SYMBOL_GPL(mddev_unlock);
 
@@ -2452,7 +2452,8 @@ static void export_rdev(struct md_rdev *rdev, struct mddev *mddev)
        if (test_bit(AutoDetected, &rdev->flags))
                md_autodetect_dev(rdev->bdev->bd_dev);
 #endif
-       blkdev_put(rdev->bdev, mddev->external ? &claim_rdev : rdev);
+       blkdev_put(rdev->bdev,
+                  test_bit(Holder, &rdev->flags) ? rdev : &claim_rdev);
        rdev->bdev = NULL;
        kobject_put(&rdev->kobj);
 }
@@ -3632,6 +3633,7 @@ EXPORT_SYMBOL_GPL(md_rdev_init);
 static struct md_rdev *md_import_device(dev_t newdev, int super_format, int super_minor)
 {
        struct md_rdev *rdev;
+       struct md_rdev *holder;
        sector_t size;
        int err;
 
@@ -3646,8 +3648,15 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
        if (err)
                goto out_clear_rdev;
 
+       if (super_format == -2) {
+               holder = &claim_rdev;
+       } else {
+               holder = rdev;
+               set_bit(Holder, &rdev->flags);
+       }
+
        rdev->bdev = blkdev_get_by_dev(newdev, BLK_OPEN_READ | BLK_OPEN_WRITE,
-                       super_format == -2 ? &claim_rdev : rdev, NULL);
+                                      holder, NULL);
        if (IS_ERR(rdev->bdev)) {
                pr_warn("md: could not open device unknown-block(%u,%u).\n",
                        MAJOR(newdev), MINOR(newdev));
@@ -3684,7 +3693,7 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
        return rdev;
 
 out_blkdev_put:
-       blkdev_put(rdev->bdev, super_format == -2 ? &claim_rdev : rdev);
+       blkdev_put(rdev->bdev, holder);
 out_clear_rdev:
        md_rdev_clear(rdev);
 out_free_rdev:
@@ -8256,7 +8265,7 @@ static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos)
        spin_unlock(&all_mddevs_lock);
 
        if (to_put)
-               mddev_put(mddev);
+               mddev_put(to_put);
        return next_mddev;
 
 }
index 9bcb77bca963922193b6d04e4a9b134ee7cd5ce7..7c9c13abd7cac00e36b5b2b44784735a645afeca 100644 (file)
@@ -211,6 +211,9 @@ enum flag_bits {
                                 * check if there is collision between raid1
                                 * serial bios.
                                 */
+       Holder,                 /* rdev is used as holder while opening
+                                * underlying disk exclusively.
+                                */
 };
 
 static inline int is_badblock(struct md_rdev *rdev, sector_t s, int sectors,
index 4b30a174216232564cd88781d603d6ac5d7e5c95..2aabac773fe72aa0db6bb6344e128b3d3dd08460 100644 (file)
@@ -1837,12 +1837,11 @@ static int raid1_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
        struct r1conf *conf = mddev->private;
        int err = 0;
        int number = rdev->raid_disk;
+       struct raid1_info *p = conf->mirrors + number;
 
        if (unlikely(number >= conf->raid_disks))
                goto abort;
 
-       struct raid1_info *p = conf->mirrors + number;
-
        if (rdev != p->rdev)
                p = conf->mirrors + conf->raid_disks + number;
 
index 0f430ddc1f6704e96dd42357eaf77f03be19793f..fd87747be9b177c07c25048a62fbbded363fab5e 100644 (file)
  * different type underlying the specified range of virtual addresses.
  * When the function isn't able to map a single page, it returns error.
  *
+ * Note that get_vaddr_frames() cannot follow VM_IO mappings. It used
+ * to be able to do that, but that could (racily) return non-refcounted
+ * pfns.
+ *
  * This function takes care of grabbing mmap_lock as necessary.
  */
 int get_vaddr_frames(unsigned long start, unsigned int nr_frames, bool write,
@@ -59,8 +63,6 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames, bool write,
        if (likely(ret > 0))
                return ret;
 
-       /* This used to (racily) return non-refcounted pfns. Let people know */
-       WARN_ONCE(1, "get_vaddr_frames() cannot follow VM_IO mapping");
        vec->nr_frames = 0;
        return ret ? ret : -EFAULT;
 }
index a1136fdfbed2d4b16f858dae07d5fa1db620b2b1..ec53abe2e84e53ef2e24a9760f10f94836340f67 100644 (file)
@@ -691,12 +691,12 @@ static int imx219_init_cfg(struct v4l2_subdev *sd,
        struct v4l2_mbus_framefmt *format;
        struct v4l2_rect *crop;
 
-       /* Initialize try_fmt */
+       /* Initialize the format. */
        format = v4l2_subdev_get_pad_format(sd, state, 0);
        imx219_update_pad_format(imx219, &supported_modes[0], format,
                                 MEDIA_BUS_FMT_SRGGB10_1X10);
 
-       /* Initialize crop rectangle. */
+       /* Initialize the crop rectangle. */
        crop = v4l2_subdev_get_pad_crop(sd, state, 0);
        crop->top = IMX219_PIXEL_ARRAY_TOP;
        crop->left = IMX219_PIXEL_ARRAY_LEFT;
@@ -750,6 +750,7 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
        const struct imx219_mode *mode;
        int exposure_max, exposure_def, hblank;
        struct v4l2_mbus_framefmt *format;
+       struct v4l2_rect *crop;
 
        mode = v4l2_find_nearest_size(supported_modes,
                                      ARRAY_SIZE(supported_modes),
@@ -757,10 +758,12 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
                                      fmt->format.width, fmt->format.height);
 
        imx219_update_pad_format(imx219, mode, &fmt->format, fmt->format.code);
+
        format = v4l2_subdev_get_pad_format(sd, sd_state, 0);
+       crop = v4l2_subdev_get_pad_crop(sd, sd_state, 0);
 
-       if (imx219->mode == mode && format->code == fmt->format.code)
-               return 0;
+       *format = fmt->format;
+       *crop = mode->crop;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
                imx219->mode = mode;
@@ -788,8 +791,6 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
                                         hblank);
        }
 
-       *format = fmt->format;
-
        return 0;
 }
 
index 20e7c7cf5eeb953d60babada315c2e020acf7d37..be84ff1e2b170562226404ded0c33f3064a1cad5 100644 (file)
@@ -1110,7 +1110,6 @@ err_async:
 
 static void max9286_v4l2_unregister(struct max9286_priv *priv)
 {
-       fwnode_handle_put(priv->sd.fwnode);
        v4l2_ctrl_handler_free(&priv->ctrls);
        v4l2_async_unregister_subdev(&priv->sd);
        max9286_v4l2_notifier_unregister(priv);
index a36a709243fdbd4390ee8d53cc20fa70d1d4fbfc..3e22df36354fdbd03e828d61d652903f854ff098 100644 (file)
@@ -608,7 +608,6 @@ static void rdacm21_remove(struct i2c_client *client)
        v4l2_async_unregister_subdev(&dev->sd);
        v4l2_ctrl_handler_free(&dev->ctrls);
        i2c_unregister_device(dev->isp);
-       fwnode_handle_put(dev->sd.fwnode);
 }
 
 static const struct of_device_id rdacm21_of_ids[] = {
index 436baf6c8b089d43efac8b4eda44dd9c22620717..241a696e374a922b6f8aa058150e75c3e42a11b7 100644 (file)
@@ -68,9 +68,7 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
        sg = sglist;
        for (line = 0; line < store_lines; line++) {
                if ((line >= (store_lines - VCR_HACK_LINES)) &&
-                   (btv->opt_vcr_hack ||
-                   (V4L2_FIELD_HAS_BOTH(btv->field) ||
-                    btv->field == V4L2_FIELD_ALTERNATE)))
+                   btv->opt_vcr_hack)
                        continue;
                while (offset && offset >= sg_dma_len(sg)) {
                        offset -= sg_dma_len(sg);
index 1ef1c4e3750d7033ca753ef71f4c01be8817af11..212753450576ae7ed88ae53558a36e979c2b5a01 100644 (file)
@@ -3,7 +3,10 @@
 
 config INTEL_VSC
        tristate "Intel Visual Sensing Controller"
-       depends on INTEL_MEI && ACPI
+       depends on INTEL_MEI && ACPI && VIDEO_DEV
+       select MEDIA_CONTROLLER
+       select VIDEO_V4L2_SUBDEV_API
+       select V4L2_ASYNC
        help
          This adds support for Intel Visual Sensing Controller (IVSC).
 
index ec1a16734a280dce566149664354b41bd34cad81..d6499ffe30e8b6a3f46ec3266de4c8d598cfdf82 100644 (file)
@@ -7,7 +7,7 @@ config VIDEO_CAFE_CCIC
        depends on V4L_PLATFORM_DRIVERS
        depends on PCI && I2C && VIDEO_DEV
        depends on COMMON_CLK
-       select VIDEO_OV7670
+       select VIDEO_OV7670 if MEDIA_SUBDRV_AUTOSELECT && VIDEO_CAMERA_SENSOR
        select VIDEOBUF2_VMALLOC
        select VIDEOBUF2_DMA_CONTIG
        select VIDEOBUF2_DMA_SG
@@ -22,7 +22,7 @@ config VIDEO_MMP_CAMERA
        depends on I2C && VIDEO_DEV
        depends on ARCH_MMP || COMPILE_TEST
        depends on COMMON_CLK
-       select VIDEO_OV7670
+       select VIDEO_OV7670 if MEDIA_SUBDRV_AUTOSELECT && VIDEO_CAMERA_SENSOR
        select I2C_GPIO
        select VIDEOBUF2_VMALLOC
        select VIDEOBUF2_DMA_CONTIG
index 16f19a6401301e01e879af3baca3fb59672ac536..5f93712bf485408cb3a7d174b4ddb44b65250ff4 100644 (file)
@@ -1490,7 +1490,6 @@ err_cleanup:
        v4l2_async_unregister_subdev(&csis->sd);
 err_disable_clock:
        mipi_csis_clk_disable(csis);
-       fwnode_handle_put(csis->sd.fwnode);
 
        return ret;
 }
@@ -1510,7 +1509,6 @@ static void mipi_csis_remove(struct platform_device *pdev)
        mipi_csis_clk_disable(csis);
        v4l2_subdev_cleanup(&csis->sd);
        media_entity_cleanup(&csis->sd.entity);
-       fwnode_handle_put(csis->sd.fwnode);
        pm_runtime_set_suspended(&pdev->dev);
 }
 
index 8926eb0803b27a0a333da2b9a6b58246092b4d5c..6e603c0382487862cf5a76e59b0dce8ed2c29896 100644 (file)
@@ -7,7 +7,7 @@ config VIDEO_VIA_CAMERA
        depends on V4L_PLATFORM_DRIVERS
        depends on FB_VIA && VIDEO_DEV
        select VIDEOBUF2_DMA_SG
-       select VIDEO_OV7670
+       select VIDEO_OV7670 if VIDEO_CAMERA_SENSOR
        help
           Driver support for the integrated camera controller in VIA
           Chrome9 chipsets.  Currently only tested on OLPC xo-1.5 systems
index b3c472b8c5a960aa81cfced5d245436d4f99364e..cb61fd6cc6c617dc36ed8f305b02a851ee8fa76f 100644 (file)
@@ -12,8 +12,8 @@ config VIDEO_EM28XX_V4L2
        select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT
        select VIDEO_TVP5150 if MEDIA_SUBDRV_AUTOSELECT
        select VIDEO_MSP3400 if MEDIA_SUBDRV_AUTOSELECT
-       select VIDEO_MT9V011 if MEDIA_SUBDRV_AUTOSELECT && MEDIA_CAMERA_SUPPORT
-       select VIDEO_OV2640 if MEDIA_SUBDRV_AUTOSELECT && MEDIA_CAMERA_SUPPORT
+       select VIDEO_MT9V011 if MEDIA_SUBDRV_AUTOSELECT && VIDEO_CAMERA_SENSOR
+       select VIDEO_OV2640 if MEDIA_SUBDRV_AUTOSELECT && VIDEO_CAMERA_SENSOR
        help
          This is a video4linux driver for Empia 28xx based TV cards.
 
index 4ff79940ad8d46664b252dc75b2b3ab792eb65e0..b2a15d9fb1f33cc7d302f3f99b30fc6921007098 100644 (file)
@@ -12,8 +12,8 @@ config VIDEO_GO7007
        select VIDEO_TW2804 if MEDIA_SUBDRV_AUTOSELECT
        select VIDEO_TW9903 if MEDIA_SUBDRV_AUTOSELECT
        select VIDEO_TW9906 if MEDIA_SUBDRV_AUTOSELECT
-       select VIDEO_OV7640 if MEDIA_SUBDRV_AUTOSELECT && MEDIA_CAMERA_SUPPORT
        select VIDEO_UDA1342 if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_OV7640 if MEDIA_SUBDRV_AUTOSELECT && VIDEO_CAMERA_SENSOR
        help
          This is a video4linux driver for the WIS GO7007 MPEG
          encoder chip.
index 5e9d3da862dd86ac84634ef8664c69866557d990..e59a463c27618ebbce7618b754c56bb41be2db3b 100644 (file)
@@ -1402,6 +1402,9 @@ int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
        query_menu->id = id;
        query_menu->index = index;
 
+       if (index >= BITS_PER_TYPE(mapping->menu_mask))
+               return -EINVAL;
+
        ret = mutex_lock_interruptible(&chain->ctrl_mutex);
        if (ret < 0)
                return -ERESTARTSYS;
index 37b23e9bae823c1b3db4ac912d0b3632175b59a1..7b6d07cbe6fc6f32cb3c850806e1ef8b7257c9b4 100644 (file)
@@ -1178,8 +1178,8 @@ err:
 }
 
 EXPORT_NS_GPL_DEV_PM_OPS(cs42l43_pm_ops, MFD_CS42L43) = {
-       SET_SYSTEM_SLEEP_PM_OPS(cs42l43_suspend, cs42l43_resume)
-       SET_RUNTIME_PM_OPS(cs42l43_runtime_suspend, cs42l43_runtime_resume, NULL)
+       SYSTEM_SLEEP_PM_OPS(cs42l43_suspend, cs42l43_resume)
+       RUNTIME_PM_OPS(cs42l43_runtime_suspend, cs42l43_runtime_resume, NULL)
 };
 
 MODULE_DESCRIPTION("CS42L43 Core Driver");
index 0617d5ccd3ff104b63bac4711a8686f2ad2179f2..8c66d3bf61f028167a98fd7025ba6b0f7b3b431d 100644 (file)
@@ -266,6 +266,8 @@ struct sja1105_private {
         * the switch doesn't confuse them with one another.
         */
        struct mutex mgmt_lock;
+       /* Serializes accesses to the FDB */
+       struct mutex fdb_lock;
        /* PTP two-step TX timestamp ID, and its serialization lock */
        spinlock_t ts_id_lock;
        u8 ts_id;
index 7729d3f8b7f50a1a8fd85f1b5f34381817228812..984c0e604e8de23fcb940bb443c10d94595433c3 100644 (file)
@@ -1175,18 +1175,15 @@ const struct sja1105_dynamic_table_ops sja1110_dyn_ops[BLK_IDX_MAX_DYN] = {
 
 static int
 sja1105_dynamic_config_poll_valid(struct sja1105_private *priv,
-                                 struct sja1105_dyn_cmd *cmd,
-                                 const struct sja1105_dynamic_table_ops *ops)
+                                 const struct sja1105_dynamic_table_ops *ops,
+                                 void *entry, bool check_valident,
+                                 bool check_errors)
 {
        u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {};
+       struct sja1105_dyn_cmd cmd = {};
        int rc;
 
-       /* We don't _need_ to read the full entry, just the command area which
-        * is a fixed SJA1105_SIZE_DYN_CMD. But our cmd_packing() API expects a
-        * buffer that contains the full entry too. Additionally, our API
-        * doesn't really know how many bytes into the buffer does the command
-        * area really begin. So just read back the whole entry.
-        */
+       /* Read back the whole entry + command structure. */
        rc = sja1105_xfer_buf(priv, SPI_READ, ops->addr, packed_buf,
                              ops->packed_size);
        if (rc)
@@ -1195,11 +1192,25 @@ sja1105_dynamic_config_poll_valid(struct sja1105_private *priv,
        /* Unpack the command structure, and return it to the caller in case it
         * needs to perform further checks on it (VALIDENT).
         */
-       memset(cmd, 0, sizeof(*cmd));
-       ops->cmd_packing(packed_buf, cmd, UNPACK);
+       ops->cmd_packing(packed_buf, &cmd, UNPACK);
 
        /* Hardware hasn't cleared VALID => still working on it */
-       return cmd->valid ? -EAGAIN : 0;
+       if (cmd.valid)
+               return -EAGAIN;
+
+       if (check_valident && !cmd.valident && !(ops->access & OP_VALID_ANYWAY))
+               return -ENOENT;
+
+       if (check_errors && cmd.errors)
+               return -EINVAL;
+
+       /* Don't dereference possibly NULL pointer - maybe caller
+        * only wanted to see whether the entry existed or not.
+        */
+       if (entry)
+               ops->entry_packing(packed_buf, entry, UNPACK);
+
+       return 0;
 }
 
 /* Poll the dynamic config entry's control area until the hardware has
@@ -1208,16 +1219,19 @@ sja1105_dynamic_config_poll_valid(struct sja1105_private *priv,
  */
 static int
 sja1105_dynamic_config_wait_complete(struct sja1105_private *priv,
-                                    struct sja1105_dyn_cmd *cmd,
-                                    const struct sja1105_dynamic_table_ops *ops)
+                                    const struct sja1105_dynamic_table_ops *ops,
+                                    void *entry, bool check_valident,
+                                    bool check_errors)
 {
-       int rc;
-
-       return read_poll_timeout(sja1105_dynamic_config_poll_valid,
-                                rc, rc != -EAGAIN,
-                                SJA1105_DYNAMIC_CONFIG_SLEEP_US,
-                                SJA1105_DYNAMIC_CONFIG_TIMEOUT_US,
-                                false, priv, cmd, ops);
+       int err, rc;
+
+       err = read_poll_timeout(sja1105_dynamic_config_poll_valid,
+                               rc, rc != -EAGAIN,
+                               SJA1105_DYNAMIC_CONFIG_SLEEP_US,
+                               SJA1105_DYNAMIC_CONFIG_TIMEOUT_US,
+                               false, priv, ops, entry, check_valident,
+                               check_errors);
+       return err < 0 ? err : rc;
 }
 
 /* Provides read access to the settings through the dynamic interface
@@ -1286,25 +1300,14 @@ int sja1105_dynamic_config_read(struct sja1105_private *priv,
        mutex_lock(&priv->dynamic_config_lock);
        rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf,
                              ops->packed_size);
-       if (rc < 0) {
-               mutex_unlock(&priv->dynamic_config_lock);
-               return rc;
-       }
-
-       rc = sja1105_dynamic_config_wait_complete(priv, &cmd, ops);
-       mutex_unlock(&priv->dynamic_config_lock);
        if (rc < 0)
-               return rc;
+               goto out;
 
-       if (!cmd.valident && !(ops->access & OP_VALID_ANYWAY))
-               return -ENOENT;
+       rc = sja1105_dynamic_config_wait_complete(priv, ops, entry, true, false);
+out:
+       mutex_unlock(&priv->dynamic_config_lock);
 
-       /* Don't dereference possibly NULL pointer - maybe caller
-        * only wanted to see whether the entry existed or not.
-        */
-       if (entry)
-               ops->entry_packing(packed_buf, entry, UNPACK);
-       return 0;
+       return rc;
 }
 
 int sja1105_dynamic_config_write(struct sja1105_private *priv,
@@ -1356,22 +1359,14 @@ int sja1105_dynamic_config_write(struct sja1105_private *priv,
        mutex_lock(&priv->dynamic_config_lock);
        rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf,
                              ops->packed_size);
-       if (rc < 0) {
-               mutex_unlock(&priv->dynamic_config_lock);
-               return rc;
-       }
-
-       rc = sja1105_dynamic_config_wait_complete(priv, &cmd, ops);
-       mutex_unlock(&priv->dynamic_config_lock);
        if (rc < 0)
-               return rc;
+               goto out;
 
-       cmd = (struct sja1105_dyn_cmd) {0};
-       ops->cmd_packing(packed_buf, &cmd, UNPACK);
-       if (cmd.errors)
-               return -EINVAL;
+       rc = sja1105_dynamic_config_wait_complete(priv, ops, NULL, false, true);
+out:
+       mutex_unlock(&priv->dynamic_config_lock);
 
-       return 0;
+       return rc;
 }
 
 static u8 sja1105_crc8_add(u8 crc, u8 byte, u8 poly)
index a23d980d28f5d190de5896ff79b106f529db566b..1a367e64bc3b1d35a708c47b34fcf8ce76d015a0 100644 (file)
@@ -1798,6 +1798,7 @@ static int sja1105_fdb_add(struct dsa_switch *ds, int port,
                           struct dsa_db db)
 {
        struct sja1105_private *priv = ds->priv;
+       int rc;
 
        if (!vid) {
                switch (db.type) {
@@ -1812,12 +1813,16 @@ static int sja1105_fdb_add(struct dsa_switch *ds, int port,
                }
        }
 
-       return priv->info->fdb_add_cmd(ds, port, addr, vid);
+       mutex_lock(&priv->fdb_lock);
+       rc = priv->info->fdb_add_cmd(ds, port, addr, vid);
+       mutex_unlock(&priv->fdb_lock);
+
+       return rc;
 }
 
-static int sja1105_fdb_del(struct dsa_switch *ds, int port,
-                          const unsigned char *addr, u16 vid,
-                          struct dsa_db db)
+static int __sja1105_fdb_del(struct dsa_switch *ds, int port,
+                            const unsigned char *addr, u16 vid,
+                            struct dsa_db db)
 {
        struct sja1105_private *priv = ds->priv;
 
@@ -1837,6 +1842,20 @@ static int sja1105_fdb_del(struct dsa_switch *ds, int port,
        return priv->info->fdb_del_cmd(ds, port, addr, vid);
 }
 
+static int sja1105_fdb_del(struct dsa_switch *ds, int port,
+                          const unsigned char *addr, u16 vid,
+                          struct dsa_db db)
+{
+       struct sja1105_private *priv = ds->priv;
+       int rc;
+
+       mutex_lock(&priv->fdb_lock);
+       rc = __sja1105_fdb_del(ds, port, addr, vid, db);
+       mutex_unlock(&priv->fdb_lock);
+
+       return rc;
+}
+
 static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
                            dsa_fdb_dump_cb_t *cb, void *data)
 {
@@ -1868,13 +1887,14 @@ static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
                if (!(l2_lookup.destports & BIT(port)))
                        continue;
 
-               /* We need to hide the FDB entry for unknown multicast */
-               if (l2_lookup.macaddr == SJA1105_UNKNOWN_MULTICAST &&
-                   l2_lookup.mask_macaddr == SJA1105_UNKNOWN_MULTICAST)
-                       continue;
-
                u64_to_ether_addr(l2_lookup.macaddr, macaddr);
 
+               /* Hardware FDB is shared for fdb and mdb, "bridge fdb show"
+                * only wants to see unicast
+                */
+               if (is_multicast_ether_addr(macaddr))
+                       continue;
+
                /* We need to hide the dsa_8021q VLANs from the user. */
                if (vid_is_dsa_8021q(l2_lookup.vlanid))
                        l2_lookup.vlanid = 0;
@@ -1898,6 +1918,8 @@ static void sja1105_fast_age(struct dsa_switch *ds, int port)
        };
        int i;
 
+       mutex_lock(&priv->fdb_lock);
+
        for (i = 0; i < SJA1105_MAX_L2_LOOKUP_COUNT; i++) {
                struct sja1105_l2_lookup_entry l2_lookup = {0};
                u8 macaddr[ETH_ALEN];
@@ -1911,7 +1933,7 @@ static void sja1105_fast_age(struct dsa_switch *ds, int port)
                if (rc) {
                        dev_err(ds->dev, "Failed to read FDB: %pe\n",
                                ERR_PTR(rc));
-                       return;
+                       break;
                }
 
                if (!(l2_lookup.destports & BIT(port)))
@@ -1923,14 +1945,16 @@ static void sja1105_fast_age(struct dsa_switch *ds, int port)
 
                u64_to_ether_addr(l2_lookup.macaddr, macaddr);
 
-               rc = sja1105_fdb_del(ds, port, macaddr, l2_lookup.vlanid, db);
+               rc = __sja1105_fdb_del(ds, port, macaddr, l2_lookup.vlanid, db);
                if (rc) {
                        dev_err(ds->dev,
                                "Failed to delete FDB entry %pM vid %lld: %pe\n",
                                macaddr, l2_lookup.vlanid, ERR_PTR(rc));
-                       return;
+                       break;
                }
        }
+
+       mutex_unlock(&priv->fdb_lock);
 }
 
 static int sja1105_mdb_add(struct dsa_switch *ds, int port,
@@ -2273,6 +2297,7 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
        int rc, i;
        s64 now;
 
+       mutex_lock(&priv->fdb_lock);
        mutex_lock(&priv->mgmt_lock);
 
        mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries;
@@ -2385,6 +2410,7 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
                goto out;
 out:
        mutex_unlock(&priv->mgmt_lock);
+       mutex_unlock(&priv->fdb_lock);
 
        return rc;
 }
@@ -2954,7 +2980,9 @@ static int sja1105_port_mcast_flood(struct sja1105_private *priv, int to,
 {
        struct sja1105_l2_lookup_entry *l2_lookup;
        struct sja1105_table *table;
-       int match;
+       int match, rc;
+
+       mutex_lock(&priv->fdb_lock);
 
        table = &priv->static_config.tables[BLK_IDX_L2_LOOKUP];
        l2_lookup = table->entries;
@@ -2967,7 +2995,8 @@ static int sja1105_port_mcast_flood(struct sja1105_private *priv, int to,
        if (match == table->entry_count) {
                NL_SET_ERR_MSG_MOD(extack,
                                   "Could not find FDB entry for unknown multicast");
-               return -ENOSPC;
+               rc = -ENOSPC;
+               goto out;
        }
 
        if (flags.val & BR_MCAST_FLOOD)
@@ -2975,10 +3004,13 @@ static int sja1105_port_mcast_flood(struct sja1105_private *priv, int to,
        else
                l2_lookup[match].destports &= ~BIT(to);
 
-       return sja1105_dynamic_config_write(priv, BLK_IDX_L2_LOOKUP,
-                                           l2_lookup[match].index,
-                                           &l2_lookup[match],
-                                           true);
+       rc = sja1105_dynamic_config_write(priv, BLK_IDX_L2_LOOKUP,
+                                         l2_lookup[match].index,
+                                         &l2_lookup[match], true);
+out:
+       mutex_unlock(&priv->fdb_lock);
+
+       return rc;
 }
 
 static int sja1105_port_pre_bridge_flags(struct dsa_switch *ds, int port,
@@ -3348,6 +3380,7 @@ static int sja1105_probe(struct spi_device *spi)
        mutex_init(&priv->ptp_data.lock);
        mutex_init(&priv->dynamic_config_lock);
        mutex_init(&priv->mgmt_lock);
+       mutex_init(&priv->fdb_lock);
        spin_lock_init(&priv->ts_id_lock);
 
        rc = sja1105_parse_dt(priv);
index 1c009b485188d4cfcf2c0dc0ff5faf8c31a1855e..ca66b747b7c5d160de5e9f70eff26ef394b67c3e 100644 (file)
@@ -1385,7 +1385,7 @@ static int adin1110_fdb_add(struct adin1110_port_priv *port_priv,
                return -ENOMEM;
 
        other_port = priv->ports[!port_priv->nr];
-       port_rules = adin1110_port_rules(port_priv, false, true);
+       port_rules = adin1110_port_rules(other_port, false, true);
        eth_broadcast_addr(mask);
 
        return adin1110_write_mac_address(other_port, mac_nr, (u8 *)fdb->addr,
index ad32ca81f7ef41365dda25dd0778e60bab2d5406..f955bde10cf90ad6375f9b97fcffc36ba174a358 100644 (file)
@@ -1833,6 +1833,9 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,
        return work_done;
 
 error:
+       if (xdp_flags & ENA_XDP_REDIRECT)
+               xdp_do_flush();
+
        adapter = netdev_priv(rx_ring->netdev);
 
        if (rc == -ENOSPC) {
index d63d321f3e7b0124e19093add27cfc252a1f7f71..41a6098eb0c2f610dfd657c639d59fdd25c1615c 100644 (file)
@@ -528,13 +528,16 @@ void bcmasp_netfilt_suspend(struct bcmasp_intf *intf)
                                  ASP_RX_FILTER_BLK_CTRL);
 }
 
-void bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs,
-                                  u32 *rule_cnt)
+int bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs,
+                                 u32 *rule_cnt)
 {
        struct bcmasp_priv *priv = intf->parent;
        int j = 0, i;
 
        for (i = 0; i < NUM_NET_FILTERS; i++) {
+               if (j == *rule_cnt)
+                       return -EMSGSIZE;
+
                if (!priv->net_filters[i].claimed ||
                    priv->net_filters[i].port != intf->port)
                        continue;
@@ -548,6 +551,8 @@ void bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs,
        }
 
        *rule_cnt = j;
+
+       return 0;
 }
 
 int bcmasp_netfilt_get_active(struct bcmasp_intf *intf)
@@ -1300,6 +1305,7 @@ static int bcmasp_probe(struct platform_device *pdev)
                if (!intf) {
                        dev_err(dev, "Cannot create eth interface %d\n", i);
                        bcmasp_remove_intfs(priv);
+                       of_node_put(intf_node);
                        goto of_put_exit;
                }
                list_add_tail(&intf->list, &priv->intfs);
index 5b512f7f5e9499e569458a9d36f6963bc7cf7c43..ec90add6b03e28889d61e53e9eab6d072ce0f1f6 100644 (file)
@@ -577,8 +577,8 @@ void bcmasp_netfilt_release(struct bcmasp_intf *intf,
 
 int bcmasp_netfilt_get_active(struct bcmasp_intf *intf);
 
-void bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs,
-                                  u32 *rule_cnt);
+int bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs,
+                                 u32 *rule_cnt);
 
 void bcmasp_netfilt_suspend(struct bcmasp_intf *intf);
 
index c4f1604d5ab39e442397b0e85b88424c0c301d48..ce6a3d56fb2395baab61779210ab0b26bd6da659 100644 (file)
@@ -335,7 +335,7 @@ static int bcmasp_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
                err = bcmasp_flow_get(intf, cmd);
                break;
        case ETHTOOL_GRXCLSRLALL:
-               bcmasp_netfilt_get_all_active(intf, rule_locs, &cmd->rule_cnt);
+               err = bcmasp_netfilt_get_all_active(intf, rule_locs, &cmd->rule_cnt);
                cmd->data = NUM_NET_FILTERS;
                break;
        default:
index 5cc0dbe12132727fb286a41d117a8091c346ec53..7551aa8068f8f794fc9beb9e6cbdf5bd8faaee18 100644 (file)
@@ -2614,6 +2614,7 @@ static int bnxt_poll_nitroa0(struct napi_struct *napi, int budget)
        struct rx_cmp_ext *rxcmp1;
        u32 cp_cons, tmp_raw_cons;
        u32 raw_cons = cpr->cp_raw_cons;
+       bool flush_xdp = false;
        u32 rx_pkts = 0;
        u8 event = 0;
 
@@ -2648,6 +2649,8 @@ static int bnxt_poll_nitroa0(struct napi_struct *napi, int budget)
                                rx_pkts++;
                        else if (rc == -EBUSY)  /* partial completion */
                                break;
+                       if (event & BNXT_REDIRECT_EVENT)
+                               flush_xdp = true;
                } else if (unlikely(TX_CMP_TYPE(txcmp) ==
                                    CMPL_BASE_TYPE_HWRM_DONE)) {
                        bnxt_hwrm_handler(bp, txcmp);
@@ -2667,6 +2670,8 @@ static int bnxt_poll_nitroa0(struct napi_struct *napi, int budget)
 
        if (event & BNXT_AGG_EVENT)
                bnxt_db_write(bp, &rxr->rx_agg_db, rxr->rx_agg_prod);
+       if (flush_xdp)
+               xdp_do_flush();
 
        if (!bnxt_has_work(bp, cpr) && rx_pkts < budget) {
                napi_complete_done(napi, rx_pkts);
index 31f664ee4d778507833fe468ee3390a43692e38e..b940dcd3ace681d6dd4cba431600f89d9a3913a6 100644 (file)
@@ -756,8 +756,6 @@ static void macb_mac_link_up(struct phylink_config *config,
                if (rx_pause)
                        ctrl |= MACB_BIT(PAE);
 
-               macb_set_tx_clk(bp, speed);
-
                /* Initialize rings & buffers as clearing MACB_BIT(TE) in link down
                 * cleared the pipeline and control registers.
                 */
@@ -777,6 +775,9 @@ static void macb_mac_link_up(struct phylink_config *config,
 
        spin_unlock_irqrestore(&bp->lock, flags);
 
+       if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC))
+               macb_set_tx_clk(bp, speed);
+
        /* Enable Rx and Tx; Enable PTP unicast */
        ctrl = macb_readl(bp, NCR);
        if (gem_has_ptp(bp))
index 716815dad7d2190c29a44603e1ef342d985c1d2f..65ec1abc944211471f5eef3d564718c2c6b566fd 100644 (file)
@@ -300,10 +300,8 @@ static void tsnep_ethtool_get_channels(struct net_device *netdev,
 {
        struct tsnep_adapter *adapter = netdev_priv(netdev);
 
-       ch->max_rx = adapter->num_rx_queues;
-       ch->max_tx = adapter->num_tx_queues;
-       ch->rx_count = adapter->num_rx_queues;
-       ch->tx_count = adapter->num_tx_queues;
+       ch->max_combined = adapter->num_queues;
+       ch->combined_count = adapter->num_queues;
 }
 
 static int tsnep_ethtool_get_ts_info(struct net_device *netdev,
index f61bd89734c588e7c5314859f7245c7e081bba87..8b992dc9bb52b499b5ced0cb24d408e705fb45b0 100644 (file)
@@ -87,8 +87,11 @@ static irqreturn_t tsnep_irq(int irq, void *arg)
 
        /* handle TX/RX queue 0 interrupt */
        if ((active & adapter->queue[0].irq_mask) != 0) {
-               tsnep_disable_irq(adapter, adapter->queue[0].irq_mask);
-               napi_schedule(&adapter->queue[0].napi);
+               if (napi_schedule_prep(&adapter->queue[0].napi)) {
+                       tsnep_disable_irq(adapter, adapter->queue[0].irq_mask);
+                       /* schedule after masking to avoid races */
+                       __napi_schedule(&adapter->queue[0].napi);
+               }
        }
 
        return IRQ_HANDLED;
@@ -99,8 +102,11 @@ static irqreturn_t tsnep_irq_txrx(int irq, void *arg)
        struct tsnep_queue *queue = arg;
 
        /* handle TX/RX queue interrupt */
-       tsnep_disable_irq(queue->adapter, queue->irq_mask);
-       napi_schedule(&queue->napi);
+       if (napi_schedule_prep(&queue->napi)) {
+               tsnep_disable_irq(queue->adapter, queue->irq_mask);
+               /* schedule after masking to avoid races */
+               __napi_schedule(&queue->napi);
+       }
 
        return IRQ_HANDLED;
 }
@@ -1728,6 +1734,10 @@ static int tsnep_poll(struct napi_struct *napi, int budget)
        if (queue->tx)
                complete = tsnep_tx_poll(queue->tx, budget);
 
+       /* handle case where we are called by netpoll with a budget of 0 */
+       if (unlikely(budget <= 0))
+               return budget;
+
        if (queue->rx) {
                done = queue->rx->xsk_pool ?
                       tsnep_rx_poll_zc(queue->rx, napi, budget) :
index b4895c7b3efd1216209653002fca98f1d7f1c897..cf50368441b783df43cb308745d49fa58a69674c 100644 (file)
@@ -3353,6 +3353,15 @@ static void hns3_set_default_feature(struct net_device *netdev)
                  NETIF_F_HW_TC);
 
        netdev->hw_enc_features |= netdev->vlan_features | NETIF_F_TSO_MANGLEID;
+
+       /* The device_version V3 hardware can't offload the checksum for IP in
+        * GRE packets, but can do it for NvGRE. So default to disable the
+        * checksum and GSO offload for GRE.
+        */
+       if (ae_dev->dev_version > HNAE3_DEVICE_VERSION_V2) {
+               netdev->features &= ~NETIF_F_GSO_GRE;
+               netdev->features &= ~NETIF_F_GSO_GRE_CSUM;
+       }
 }
 
 static int hns3_alloc_buffer(struct hns3_enet_ring *ring,
index 8ca368424436205c00951112a2ed7abaf4700153..c42574e297476bdd1209e4a3090345c9a4e13b3c 100644 (file)
@@ -3564,9 +3564,14 @@ static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
 static void hclge_clear_event_cause(struct hclge_dev *hdev, u32 event_type,
                                    u32 regclr)
 {
+#define HCLGE_IMP_RESET_DELAY          5
+
        switch (event_type) {
        case HCLGE_VECTOR0_EVENT_PTP:
        case HCLGE_VECTOR0_EVENT_RST:
+               if (regclr == BIT(HCLGE_VECTOR0_IMPRESET_INT_B))
+                       mdelay(HCLGE_IMP_RESET_DELAY);
+
                hclge_write_dev(&hdev->hw, HCLGE_MISC_RESET_STS_REG, regclr);
                break;
        case HCLGE_VECTOR0_EVENT_MBX:
@@ -7348,6 +7353,12 @@ static int hclge_del_cls_flower(struct hnae3_handle *handle,
        ret = hclge_fd_tcam_config(hdev, HCLGE_FD_STAGE_1, true, rule->location,
                                   NULL, false);
        if (ret) {
+               /* if tcam config fail, set rule state to TO_DEL,
+                * so the rule will be deleted when periodic
+                * task being scheduled.
+                */
+               hclge_update_fd_list(hdev, HCLGE_FD_TO_DEL, rule->location, NULL);
+               set_bit(HCLGE_STATE_FD_TBL_CHANGED, &hdev->state);
                spin_unlock_bh(&hdev->fd_rule_lock);
                return ret;
        }
@@ -8824,7 +8835,7 @@ static void hclge_update_overflow_flags(struct hclge_vport *vport,
        if (mac_type == HCLGE_MAC_ADDR_UC) {
                if (is_all_added)
                        vport->overflow_promisc_flags &= ~HNAE3_OVERFLOW_UPE;
-               else
+               else if (hclge_is_umv_space_full(vport, true))
                        vport->overflow_promisc_flags |= HNAE3_OVERFLOW_UPE;
        } else {
                if (is_all_added)
index 7a2f9233d69548d1a5be39ccb449c3c2708e2950..a4d68fb216fb92ae4a23b24d323dade62676abea 100644 (file)
@@ -1855,7 +1855,8 @@ static void hclgevf_periodic_service_task(struct hclgevf_dev *hdev)
        unsigned long delta = round_jiffies_relative(HZ);
        struct hnae3_handle *handle = &hdev->nic;
 
-       if (test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state))
+       if (test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state) ||
+           test_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hdev->hw.hw.comm_state))
                return;
 
        if (time_is_after_jiffies(hdev->last_serv_processed + HZ)) {
index 9406237c461e0c3664a40231d4cd6939002c7db4..f81a43d2cdfcd92c46c69e2c7e866912657ae07e 100644 (file)
@@ -456,9 +456,6 @@ int hinic_set_vlan_fliter(struct hinic_dev *nic_dev, u32 en)
        u16 out_size = sizeof(vlan_filter);
        int err;
 
-       if (!hwdev)
-               return -EINVAL;
-
        vlan_filter.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
        vlan_filter.enable = en;
 
index 8ea1a238dcefe1145833fc387444d8ebbdea4bb3..d3d6415553ed671bd433bf15173564abd5f3f30c 100644 (file)
@@ -4475,9 +4475,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
                goto error_pvid;
 
        i40e_vlan_stripping_enable(vsi);
-       i40e_vc_reset_vf(vf, true);
-       /* During reset the VF got a new VSI, so refresh a pointer. */
-       vsi = pf->vsi[vf->lan_vsi_idx];
+
        /* Locked once because multiple functions below iterate list */
        spin_lock_bh(&vsi->mac_filter_hash_lock);
 
@@ -4563,6 +4561,10 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
         */
        vf->port_vlan_id = le16_to_cpu(vsi->info.pvid);
 
+       i40e_vc_reset_vf(vf, true);
+       /* During reset the VF got a new VSI, so refresh a pointer. */
+       vsi = pf->vsi[vf->lan_vsi_idx];
+
        ret = i40e_config_vf_promiscuous_mode(vf, vsi->id, allmulti, alluni);
        if (ret) {
                dev_err(&pf->pdev->dev, "Unable to config vf promiscuous mode\n");
index 85fba85fbb232bf869a988892f90084d92b3629a..e110ba3461857b0abf54d872df9a55ef282f00e6 100644 (file)
@@ -521,7 +521,7 @@ void iavf_down(struct iavf_adapter *adapter);
 int iavf_process_config(struct iavf_adapter *adapter);
 int iavf_parse_vf_resource_msg(struct iavf_adapter *adapter);
 void iavf_schedule_reset(struct iavf_adapter *adapter, u64 flags);
-void iavf_schedule_request_stats(struct iavf_adapter *adapter);
+void iavf_schedule_aq_request(struct iavf_adapter *adapter, u64 flags);
 void iavf_schedule_finish_config(struct iavf_adapter *adapter);
 void iavf_reset(struct iavf_adapter *adapter);
 void iavf_set_ethtool_ops(struct net_device *netdev);
index a34303ad057d005c7289ec161562ed916b5d7827..90397293525f7169a7bb15ae2c4866d5ffd30fdc 100644 (file)
@@ -362,7 +362,7 @@ static void iavf_get_ethtool_stats(struct net_device *netdev,
        unsigned int i;
 
        /* Explicitly request stats refresh */
-       iavf_schedule_request_stats(adapter);
+       iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_REQUEST_STATS);
 
        iavf_add_ethtool_stats(&data, adapter, iavf_gstrings_stats);
 
index 7b300c86ceda733a94222472a77aa3e9d8e68b5d..6a2e6d64bc3a5436348b902f3d55767ad2d8194c 100644 (file)
@@ -314,15 +314,13 @@ void iavf_schedule_reset(struct iavf_adapter *adapter, u64 flags)
 }
 
 /**
- * iavf_schedule_request_stats - Set the flags and schedule statistics request
+ * iavf_schedule_aq_request - Set the flags and schedule aq request
  * @adapter: board private structure
- *
- * Sets IAVF_FLAG_AQ_REQUEST_STATS flag so iavf_watchdog_task() will explicitly
- * request and refresh ethtool stats
+ * @flags: requested aq flags
  **/
-void iavf_schedule_request_stats(struct iavf_adapter *adapter)
+void iavf_schedule_aq_request(struct iavf_adapter *adapter, u64 flags)
 {
-       adapter->aq_required |= IAVF_FLAG_AQ_REQUEST_STATS;
+       adapter->aq_required |= flags;
        mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
 }
 
@@ -823,7 +821,7 @@ iavf_vlan_filter *iavf_add_vlan(struct iavf_adapter *adapter,
                list_add_tail(&f->list, &adapter->vlan_filter_list);
                f->state = IAVF_VLAN_ADD;
                adapter->num_vlan_filters++;
-               adapter->aq_required |= IAVF_FLAG_AQ_ADD_VLAN_FILTER;
+               iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_ADD_VLAN_FILTER);
        }
 
 clearout:
@@ -845,7 +843,7 @@ static void iavf_del_vlan(struct iavf_adapter *adapter, struct iavf_vlan vlan)
        f = iavf_find_vlan(adapter, vlan);
        if (f) {
                f->state = IAVF_VLAN_REMOVE;
-               adapter->aq_required |= IAVF_FLAG_AQ_DEL_VLAN_FILTER;
+               iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_DEL_VLAN_FILTER);
        }
 
        spin_unlock_bh(&adapter->mac_vlan_list_lock);
@@ -1421,7 +1419,8 @@ void iavf_down(struct iavf_adapter *adapter)
        iavf_clear_fdir_filters(adapter);
        iavf_clear_adv_rss_conf(adapter);
 
-       if (!(adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)) {
+       if (!(adapter->flags & IAVF_FLAG_PF_COMMS_FAILED) &&
+           !(test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section))) {
                /* cancel any current operation */
                adapter->current_op = VIRTCHNL_OP_UNKNOWN;
                /* Schedule operations to close down the HW. Don't wait
index 13ba9c74bd848e5eb26248abc378776a3cc1fc96..76b34cee1da3c8d9a18d3254be5b88f79882ff53 100644 (file)
@@ -3827,8 +3827,11 @@ static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs, bool reinit)
        }
 
        /* only call pci_enable_sriov() if no VFs are allocated already */
-       if (!old_vfs)
+       if (!old_vfs) {
                err = pci_enable_sriov(pdev, adapter->vfs_allocated_count);
+               if (err)
+                       goto err_out;
+       }
 
        goto out;
 
index 93bce729be76a69c562ee5523bd521466356168b..7ab6dd58e40013614a9174686200841393530e30 100644 (file)
@@ -868,6 +868,18 @@ static void igc_ethtool_get_stats(struct net_device *netdev,
        spin_unlock(&adapter->stats64_lock);
 }
 
+static int igc_ethtool_get_previous_rx_coalesce(struct igc_adapter *adapter)
+{
+       return (adapter->rx_itr_setting <= 3) ?
+               adapter->rx_itr_setting : adapter->rx_itr_setting >> 2;
+}
+
+static int igc_ethtool_get_previous_tx_coalesce(struct igc_adapter *adapter)
+{
+       return (adapter->tx_itr_setting <= 3) ?
+               adapter->tx_itr_setting : adapter->tx_itr_setting >> 2;
+}
+
 static int igc_ethtool_get_coalesce(struct net_device *netdev,
                                    struct ethtool_coalesce *ec,
                                    struct kernel_ethtool_coalesce *kernel_coal,
@@ -875,17 +887,8 @@ static int igc_ethtool_get_coalesce(struct net_device *netdev,
 {
        struct igc_adapter *adapter = netdev_priv(netdev);
 
-       if (adapter->rx_itr_setting <= 3)
-               ec->rx_coalesce_usecs = adapter->rx_itr_setting;
-       else
-               ec->rx_coalesce_usecs = adapter->rx_itr_setting >> 2;
-
-       if (!(adapter->flags & IGC_FLAG_QUEUE_PAIRS)) {
-               if (adapter->tx_itr_setting <= 3)
-                       ec->tx_coalesce_usecs = adapter->tx_itr_setting;
-               else
-                       ec->tx_coalesce_usecs = adapter->tx_itr_setting >> 2;
-       }
+       ec->rx_coalesce_usecs = igc_ethtool_get_previous_rx_coalesce(adapter);
+       ec->tx_coalesce_usecs = igc_ethtool_get_previous_tx_coalesce(adapter);
 
        return 0;
 }
@@ -910,8 +913,12 @@ static int igc_ethtool_set_coalesce(struct net_device *netdev,
            ec->tx_coalesce_usecs == 2)
                return -EINVAL;
 
-       if ((adapter->flags & IGC_FLAG_QUEUE_PAIRS) && ec->tx_coalesce_usecs)
+       if ((adapter->flags & IGC_FLAG_QUEUE_PAIRS) &&
+           ec->tx_coalesce_usecs != igc_ethtool_get_previous_tx_coalesce(adapter)) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Queue Pair mode enabled, both Rx and Tx coalescing controlled by rx-usecs");
                return -EINVAL;
+       }
 
        /* If ITR is disabled, disable DMAC */
        if (ec->rx_coalesce_usecs == 0) {
index 293b4571768384d2116dcc4a66c368e842436926..98de34d0ce07e1a6915f5eb5befee3a619572d9b 100644 (file)
@@ -6491,7 +6491,7 @@ static int igc_xdp_xmit(struct net_device *dev, int num_frames,
        struct igc_ring *ring;
        int i, drops;
 
-       if (unlikely(test_bit(__IGC_DOWN, &adapter->state)))
+       if (unlikely(!netif_carrier_ok(dev)))
                return -ENETDOWN;
 
        if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
index 0310af851086bbd5cf7253c2b52d04423de52c14..9339edbd90821af008ded99335d017145fcaeb13 100644 (file)
@@ -979,6 +979,7 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter,
        u32 tsync_tx_ctl = IXGBE_TSYNCTXCTL_ENABLED;
        u32 tsync_rx_ctl = IXGBE_TSYNCRXCTL_ENABLED;
        u32 tsync_rx_mtrl = PTP_EV_PORT << 16;
+       u32 aflags = adapter->flags;
        bool is_l2 = false;
        u32 regval;
 
@@ -996,20 +997,20 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter,
        case HWTSTAMP_FILTER_NONE:
                tsync_rx_ctl = 0;
                tsync_rx_mtrl = 0;
-               adapter->flags &= ~(IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
-                                   IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
+               aflags &= ~(IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
+                           IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
                break;
        case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
                tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
                tsync_rx_mtrl |= IXGBE_RXMTRL_V1_SYNC_MSG;
-               adapter->flags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
-                                  IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
+               aflags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
+                          IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
                break;
        case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
                tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
                tsync_rx_mtrl |= IXGBE_RXMTRL_V1_DELAY_REQ_MSG;
-               adapter->flags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
-                                  IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
+               aflags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
+                          IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
                break;
        case HWTSTAMP_FILTER_PTP_V2_EVENT:
        case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
@@ -1023,8 +1024,8 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter,
                tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_EVENT_V2;
                is_l2 = true;
                config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
-               adapter->flags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
-                                  IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
+               aflags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
+                          IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
                break;
        case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
        case HWTSTAMP_FILTER_NTP_ALL:
@@ -1035,7 +1036,7 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter,
                if (hw->mac.type >= ixgbe_mac_X550) {
                        tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_ALL;
                        config->rx_filter = HWTSTAMP_FILTER_ALL;
-                       adapter->flags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED;
+                       aflags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED;
                        break;
                }
                fallthrough;
@@ -1046,8 +1047,6 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter,
                 * Delay_Req messages and hardware does not support
                 * timestamping all packets => return error
                 */
-               adapter->flags &= ~(IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
-                                   IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
                config->rx_filter = HWTSTAMP_FILTER_NONE;
                return -ERANGE;
        }
@@ -1079,8 +1078,8 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter,
                               IXGBE_TSYNCRXCTL_TYPE_ALL |
                               IXGBE_TSYNCRXCTL_TSIP_UT_EN;
                config->rx_filter = HWTSTAMP_FILTER_ALL;
-               adapter->flags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED;
-               adapter->flags &= ~IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER;
+               aflags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED;
+               aflags &= ~IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER;
                is_l2 = true;
                break;
        default:
@@ -1113,6 +1112,9 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter,
 
        IXGBE_WRITE_FLUSH(hw);
 
+       /* configure adapter flags only when HW is actually configured */
+       adapter->flags = aflags;
+
        /* clear TX/RX time stamp registers, just to be sure */
        ixgbe_ptp_clear_tx_timestamp(adapter);
        IXGBE_READ_REG(hw, IXGBE_RXSTMPH);
index eb74ccddb4409762cbc01cf24b9bb53a95dd250d..21c3f9b015c85de6e94e9f36bf6f84df261ae295 100644 (file)
@@ -5586,6 +5586,11 @@ static int mvpp2_ethtool_get_rxnfc(struct net_device *dev,
                break;
        case ETHTOOL_GRXCLSRLALL:
                for (i = 0; i < MVPP2_N_RFS_ENTRIES_PER_FLOW; i++) {
+                       if (loc == info->rule_cnt) {
+                               ret = -EMSGSIZE;
+                               break;
+                       }
+
                        if (port->rfs_rules[i])
                                rules[loc++] = i;
                }
index 4424de2ffd70ca6762cfd1666ac326163bc9527e..dbc518ff827688a72ad2e13a3648d8c0c482d3f5 100644 (file)
@@ -734,13 +734,13 @@ static netdev_tx_t octep_start_xmit(struct sk_buff *skb,
 dma_map_sg_err:
        if (si > 0) {
                dma_unmap_single(iq->dev, sglist[0].dma_ptr[0],
-                                sglist[0].len[0], DMA_TO_DEVICE);
-               sglist[0].len[0] = 0;
+                                sglist[0].len[3], DMA_TO_DEVICE);
+               sglist[0].len[3] = 0;
        }
        while (si > 1) {
                dma_unmap_page(iq->dev, sglist[si >> 2].dma_ptr[si & 3],
-                              sglist[si >> 2].len[si & 3], DMA_TO_DEVICE);
-               sglist[si >> 2].len[si & 3] = 0;
+                              sglist[si >> 2].len[3 - (si & 3)], DMA_TO_DEVICE);
+               sglist[si >> 2].len[3 - (si & 3)] = 0;
                si--;
        }
        tx_buffer->gather = 0;
index 5a520d37bea02459815f868f889053949c4d3ce3..d0adb82d65c31eddccdb6b56522ce91e3d021fee 100644 (file)
@@ -69,12 +69,12 @@ int octep_iq_process_completions(struct octep_iq *iq, u16 budget)
                compl_sg++;
 
                dma_unmap_single(iq->dev, tx_buffer->sglist[0].dma_ptr[0],
-                                tx_buffer->sglist[0].len[0], DMA_TO_DEVICE);
+                                tx_buffer->sglist[0].len[3], DMA_TO_DEVICE);
 
                i = 1; /* entry 0 is main skb, unmapped above */
                while (frags--) {
                        dma_unmap_page(iq->dev, tx_buffer->sglist[i >> 2].dma_ptr[i & 3],
-                                      tx_buffer->sglist[i >> 2].len[i & 3], DMA_TO_DEVICE);
+                                      tx_buffer->sglist[i >> 2].len[3 - (i & 3)], DMA_TO_DEVICE);
                        i++;
                }
 
@@ -131,13 +131,13 @@ static void octep_iq_free_pending(struct octep_iq *iq)
 
                dma_unmap_single(iq->dev,
                                 tx_buffer->sglist[0].dma_ptr[0],
-                                tx_buffer->sglist[0].len[0],
+                                tx_buffer->sglist[0].len[3],
                                 DMA_TO_DEVICE);
 
                i = 1; /* entry 0 is main skb, unmapped above */
                while (frags--) {
                        dma_unmap_page(iq->dev, tx_buffer->sglist[i >> 2].dma_ptr[i & 3],
-                                      tx_buffer->sglist[i >> 2].len[i & 3], DMA_TO_DEVICE);
+                                      tx_buffer->sglist[i >> 2].len[3 - (i & 3)], DMA_TO_DEVICE);
                        i++;
                }
 
index 2ef57980eb47b8ee44c22c40acb9d18355f58956..21e75ff9f5e71165be04cdefd72678bd5911a663 100644 (file)
 #define TX_BUFTYPE_NET_SG        2
 #define NUM_TX_BUFTYPES          3
 
-/* Hardware format for Scatter/Gather list */
+/* Hardware format for Scatter/Gather list
+ *
+ * 63      48|47     32|31     16|15       0
+ * -----------------------------------------
+ * |  Len 0  |  Len 1  |  Len 2  |  Len 3  |
+ * -----------------------------------------
+ * |                Ptr 0                  |
+ * -----------------------------------------
+ * |                Ptr 1                  |
+ * -----------------------------------------
+ * |                Ptr 2                  |
+ * -----------------------------------------
+ * |                Ptr 3                  |
+ * -----------------------------------------
+ */
 struct octep_tx_sglist_desc {
        u16 len[4];
        dma_addr_t dma_ptr[4];
index 826f691de2595bb67ab7e5499deacd9c481aab26..a4a258da8dd59aca6d6832ca0ca77d9d091d38f8 100644 (file)
@@ -107,12 +107,13 @@ int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura)
 }
 
 #define NPA_MAX_BURST 16
-void cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
+int cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
 {
        struct otx2_nic *pfvf = dev;
+       int cnt = cq->pool_ptrs;
        u64 ptrs[NPA_MAX_BURST];
-       int num_ptrs = 1;
        dma_addr_t bufptr;
+       int num_ptrs = 1;
 
        /* Refill pool with new buffers */
        while (cq->pool_ptrs) {
@@ -131,6 +132,7 @@ void cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
                        num_ptrs = 1;
                }
        }
+       return cnt - cq->pool_ptrs;
 }
 
 void cn10k_sqe_flush(void *dev, struct otx2_snd_queue *sq, int size, int qidx)
index 8ae96815865e6a2ca03878daa694d5cb5da2cd88..c1861f7de254500a659892fcbd1bed835cff2d98 100644 (file)
@@ -24,7 +24,7 @@ static inline int mtu_to_dwrr_weight(struct otx2_nic *pfvf, int mtu)
        return weight;
 }
 
-void cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq);
+int cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq);
 void cn10k_sqe_flush(void *dev, struct otx2_snd_queue *sq, int size, int qidx);
 int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura);
 int cn10k_lmtst_init(struct otx2_nic *pfvf);
index 8511906cb4e2d300034cecfb41648f723acd3546..997fedac3a98fdfeadf0f481805477ce295638db 100644 (file)
@@ -574,20 +574,8 @@ int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
 int otx2_alloc_buffer(struct otx2_nic *pfvf, struct otx2_cq_queue *cq,
                      dma_addr_t *dma)
 {
-       if (unlikely(__otx2_alloc_rbuf(pfvf, cq->rbpool, dma))) {
-               struct refill_work *work;
-               struct delayed_work *dwork;
-
-               work = &pfvf->refill_wrk[cq->cq_idx];
-               dwork = &work->pool_refill_work;
-               /* Schedule a task if no other task is running */
-               if (!cq->refill_task_sched) {
-                       cq->refill_task_sched = true;
-                       schedule_delayed_work(dwork,
-                                             msecs_to_jiffies(100));
-               }
+       if (unlikely(__otx2_alloc_rbuf(pfvf, cq->rbpool, dma)))
                return -ENOMEM;
-       }
        return 0;
 }
 
@@ -1082,39 +1070,20 @@ static int otx2_cq_init(struct otx2_nic *pfvf, u16 qidx)
 static void otx2_pool_refill_task(struct work_struct *work)
 {
        struct otx2_cq_queue *cq;
-       struct otx2_pool *rbpool;
        struct refill_work *wrk;
-       int qidx, free_ptrs = 0;
        struct otx2_nic *pfvf;
-       dma_addr_t bufptr;
+       int qidx;
 
        wrk = container_of(work, struct refill_work, pool_refill_work.work);
        pfvf = wrk->pf;
        qidx = wrk - pfvf->refill_wrk;
        cq = &pfvf->qset.cq[qidx];
-       rbpool = cq->rbpool;
-       free_ptrs = cq->pool_ptrs;
 
-       while (cq->pool_ptrs) {
-               if (otx2_alloc_rbuf(pfvf, rbpool, &bufptr)) {
-                       /* Schedule a WQ if we fails to free atleast half of the
-                        * pointers else enable napi for this RQ.
-                        */
-                       if (!((free_ptrs - cq->pool_ptrs) > free_ptrs / 2)) {
-                               struct delayed_work *dwork;
-
-                               dwork = &wrk->pool_refill_work;
-                               schedule_delayed_work(dwork,
-                                                     msecs_to_jiffies(100));
-                       } else {
-                               cq->refill_task_sched = false;
-                       }
-                       return;
-               }
-               pfvf->hw_ops->aura_freeptr(pfvf, qidx, bufptr + OTX2_HEAD_ROOM);
-               cq->pool_ptrs--;
-       }
        cq->refill_task_sched = false;
+
+       local_bh_disable();
+       napi_schedule(wrk->napi);
+       local_bh_enable();
 }
 
 int otx2_config_nix_queues(struct otx2_nic *pfvf)
index 4c6032ee7800de07e646bc3ec4f2f955a6ed5824..c04a8ee53a82f1711ea62164b764b92a9d2244cc 100644 (file)
@@ -302,6 +302,7 @@ struct flr_work {
 struct refill_work {
        struct delayed_work pool_refill_work;
        struct otx2_nic *pf;
+       struct napi_struct *napi;
 };
 
 /* PTPv2 originTimestamp structure */
@@ -370,7 +371,7 @@ struct dev_hw_ops {
        int     (*sq_aq_init)(void *dev, u16 qidx, u16 sqb_aura);
        void    (*sqe_flush)(void *dev, struct otx2_snd_queue *sq,
                             int size, int qidx);
-       void    (*refill_pool_ptrs)(void *dev, struct otx2_cq_queue *cq);
+       int     (*refill_pool_ptrs)(void *dev, struct otx2_cq_queue *cq);
        void    (*aura_freeptr)(void *dev, int aura, u64 buf);
 };
 
index 70b9065f7d10188180b8aa16e2b37c85d1ff7176..6daf4d58c25d6379c5e78689d8d91b301927a186 100644 (file)
@@ -1943,6 +1943,10 @@ int otx2_stop(struct net_device *netdev)
 
        netif_tx_disable(netdev);
 
+       for (wrk = 0; wrk < pf->qset.cq_cnt; wrk++)
+               cancel_delayed_work_sync(&pf->refill_wrk[wrk].pool_refill_work);
+       devm_kfree(pf->dev, pf->refill_wrk);
+
        otx2_free_hw_resources(pf);
        otx2_free_cints(pf, pf->hw.cint_cnt);
        otx2_disable_napi(pf);
@@ -1950,9 +1954,6 @@ int otx2_stop(struct net_device *netdev)
        for (qidx = 0; qidx < netdev->num_tx_queues; qidx++)
                netdev_tx_reset_queue(netdev_get_tx_queue(netdev, qidx));
 
-       for (wrk = 0; wrk < pf->qset.cq_cnt; wrk++)
-               cancel_delayed_work_sync(&pf->refill_wrk[wrk].pool_refill_work);
-       devm_kfree(pf->dev, pf->refill_wrk);
 
        kfree(qset->sq);
        kfree(qset->cq);
index e369baf115301df919a2b315e3709d82f931e4a0..53b2a4ef52985271ab6d0ee67c779af878876ba0 100644 (file)
@@ -29,7 +29,8 @@
 static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf,
                                     struct bpf_prog *prog,
                                     struct nix_cqe_rx_s *cqe,
-                                    struct otx2_cq_queue *cq);
+                                    struct otx2_cq_queue *cq,
+                                    bool *need_xdp_flush);
 
 static int otx2_nix_cq_op_status(struct otx2_nic *pfvf,
                                 struct otx2_cq_queue *cq)
@@ -337,7 +338,7 @@ static bool otx2_check_rcv_errors(struct otx2_nic *pfvf,
 static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
                                 struct napi_struct *napi,
                                 struct otx2_cq_queue *cq,
-                                struct nix_cqe_rx_s *cqe)
+                                struct nix_cqe_rx_s *cqe, bool *need_xdp_flush)
 {
        struct nix_rx_parse_s *parse = &cqe->parse;
        struct nix_rx_sg_s *sg = &cqe->sg;
@@ -353,7 +354,7 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
        }
 
        if (pfvf->xdp_prog)
-               if (otx2_xdp_rcv_pkt_handler(pfvf, pfvf->xdp_prog, cqe, cq))
+               if (otx2_xdp_rcv_pkt_handler(pfvf, pfvf->xdp_prog, cqe, cq, need_xdp_flush))
                        return;
 
        skb = napi_get_frags(napi);
@@ -388,6 +389,7 @@ static int otx2_rx_napi_handler(struct otx2_nic *pfvf,
                                struct napi_struct *napi,
                                struct otx2_cq_queue *cq, int budget)
 {
+       bool need_xdp_flush = false;
        struct nix_cqe_rx_s *cqe;
        int processed_cqe = 0;
 
@@ -409,13 +411,15 @@ process_cqe:
                cq->cq_head++;
                cq->cq_head &= (cq->cqe_cnt - 1);
 
-               otx2_rcv_pkt_handler(pfvf, napi, cq, cqe);
+               otx2_rcv_pkt_handler(pfvf, napi, cq, cqe, &need_xdp_flush);
 
                cqe->hdr.cqe_type = NIX_XQE_TYPE_INVALID;
                cqe->sg.seg_addr = 0x00;
                processed_cqe++;
                cq->pend_cqe--;
        }
+       if (need_xdp_flush)
+               xdp_do_flush();
 
        /* Free CQEs to HW */
        otx2_write64(pfvf, NIX_LF_CQ_OP_DOOR,
@@ -424,9 +428,10 @@ process_cqe:
        return processed_cqe;
 }
 
-void otx2_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
+int otx2_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
 {
        struct otx2_nic *pfvf = dev;
+       int cnt = cq->pool_ptrs;
        dma_addr_t bufptr;
 
        while (cq->pool_ptrs) {
@@ -435,6 +440,8 @@ void otx2_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
                otx2_aura_freeptr(pfvf, cq->cq_idx, bufptr + OTX2_HEAD_ROOM);
                cq->pool_ptrs--;
        }
+
+       return cnt - cq->pool_ptrs;
 }
 
 static int otx2_tx_napi_handler(struct otx2_nic *pfvf,
@@ -521,6 +528,7 @@ int otx2_napi_handler(struct napi_struct *napi, int budget)
        struct otx2_cq_queue *cq;
        struct otx2_qset *qset;
        struct otx2_nic *pfvf;
+       int filled_cnt = -1;
 
        cq_poll = container_of(napi, struct otx2_cq_poll, napi);
        pfvf = (struct otx2_nic *)cq_poll->dev;
@@ -541,7 +549,7 @@ int otx2_napi_handler(struct napi_struct *napi, int budget)
        }
 
        if (rx_cq && rx_cq->pool_ptrs)
-               pfvf->hw_ops->refill_pool_ptrs(pfvf, rx_cq);
+               filled_cnt = pfvf->hw_ops->refill_pool_ptrs(pfvf, rx_cq);
        /* Clear the IRQ */
        otx2_write64(pfvf, NIX_LF_CINTX_INT(cq_poll->cint_idx), BIT_ULL(0));
 
@@ -561,9 +569,25 @@ int otx2_napi_handler(struct napi_struct *napi, int budget)
                                otx2_config_irq_coalescing(pfvf, i);
                }
 
-               /* Re-enable interrupts */
-               otx2_write64(pfvf, NIX_LF_CINTX_ENA_W1S(cq_poll->cint_idx),
-                            BIT_ULL(0));
+               if (unlikely(!filled_cnt)) {
+                       struct refill_work *work;
+                       struct delayed_work *dwork;
+
+                       work = &pfvf->refill_wrk[cq->cq_idx];
+                       dwork = &work->pool_refill_work;
+                       /* Schedule a task if no other task is running */
+                       if (!cq->refill_task_sched) {
+                               work->napi = napi;
+                               cq->refill_task_sched = true;
+                               schedule_delayed_work(dwork,
+                                                     msecs_to_jiffies(100));
+                       }
+               } else {
+                       /* Re-enable interrupts */
+                       otx2_write64(pfvf,
+                                    NIX_LF_CINTX_ENA_W1S(cq_poll->cint_idx),
+                                    BIT_ULL(0));
+               }
        }
        return workdone;
 }
@@ -1334,7 +1358,8 @@ bool otx2_xdp_sq_append_pkt(struct otx2_nic *pfvf, u64 iova, int len, u16 qidx)
 static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf,
                                     struct bpf_prog *prog,
                                     struct nix_cqe_rx_s *cqe,
-                                    struct otx2_cq_queue *cq)
+                                    struct otx2_cq_queue *cq,
+                                    bool *need_xdp_flush)
 {
        unsigned char *hard_start, *data;
        int qidx = cq->cq_idx;
@@ -1371,8 +1396,10 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf,
 
                otx2_dma_unmap_page(pfvf, iova, pfvf->rbsize,
                                    DMA_FROM_DEVICE);
-               if (!err)
+               if (!err) {
+                       *need_xdp_flush = true;
                        return true;
+               }
                put_page(page);
                break;
        default:
index 9e3bfbe5c480946da799ae02adff5e489afb0b10..a82ffca8ce1b1bcf9b9fc0b9d0707da79d3ac3e1 100644 (file)
@@ -170,6 +170,6 @@ void cn10k_sqe_flush(void *dev, struct otx2_snd_queue *sq,
                     int size, int qidx);
 void otx2_sqe_flush(void *dev, struct otx2_snd_queue *sq,
                    int size, int qidx);
-void otx2_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq);
-void cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq);
+int otx2_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq);
+int cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq);
 #endif /* OTX2_TXRX_H */
index 6ad42e3b488f7b4f0a8abeb419285a7f1906f18d..3cffd1bd306777e5a79ff23a47558622d9e8d82d 100644 (file)
@@ -2005,11 +2005,11 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
        u8 *data, *new_data;
        struct mtk_rx_dma_v2 *rxd, trxd;
        int done = 0, bytes = 0;
+       dma_addr_t dma_addr = DMA_MAPPING_ERROR;
 
        while (done < budget) {
                unsigned int pktlen, *rxdcsum;
                struct net_device *netdev;
-               dma_addr_t dma_addr;
                u32 hash, reason;
                int mac = 0;
 
@@ -2186,7 +2186,8 @@ release_desc:
                else
                        rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size);
 
-               if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA))
+               if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA) &&
+                   likely(dma_addr != DMA_MAPPING_ERROR))
                        rxd->rxd2 |= RX_DMA_PREP_ADDR64(dma_addr);
 
                ring->calc_idx = idx;
@@ -2994,6 +2995,9 @@ static int mtk_hwlro_get_fdir_all(struct net_device *dev,
        int i;
 
        for (i = 0; i < MTK_MAX_LRO_IP_CNT; i++) {
+               if (cnt == cmd->rule_cnt)
+                       return -EMSGSIZE;
+
                if (mac->hwlro_ip[i]) {
                        rule_locs[cnt] = i;
                        cnt++;
index a70a5417c1734b7e3126147cc66c2a0444205727..a4efbeb162084134d5c43457c20d289bad33a138 100644 (file)
@@ -214,9 +214,11 @@ mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe,
        dsa_port = mtk_flow_get_dsa_port(&dev);
 
        if (dev == eth->netdev[0])
-               pse_port = 1;
+               pse_port = PSE_GDM1_PORT;
        else if (dev == eth->netdev[1])
-               pse_port = 2;
+               pse_port = PSE_GDM2_PORT;
+       else if (dev == eth->netdev[2])
+               pse_port = PSE_GDM3_PORT;
        else
                return -EOPNOTSUPP;
 
index 300fe1a93dce81f78463d0e96c99b7eeea97ee7a..ef980e4e5bc2fa22fce9a064116a3393b50df107 100644 (file)
@@ -1021,18 +1021,32 @@ static struct vcap_rule_internal *vcap_dup_rule(struct vcap_rule_internal *ri,
        list_for_each_entry(ckf, &ri->data.keyfields, ctrl.list) {
                newckf = kmemdup(ckf, sizeof(*newckf), GFP_KERNEL);
                if (!newckf)
-                       return ERR_PTR(-ENOMEM);
+                       goto err;
                list_add_tail(&newckf->ctrl.list, &duprule->data.keyfields);
        }
 
        list_for_each_entry(caf, &ri->data.actionfields, ctrl.list) {
                newcaf = kmemdup(caf, sizeof(*newcaf), GFP_KERNEL);
                if (!newcaf)
-                       return ERR_PTR(-ENOMEM);
+                       goto err;
                list_add_tail(&newcaf->ctrl.list, &duprule->data.actionfields);
        }
 
        return duprule;
+
+err:
+       list_for_each_entry_safe(ckf, newckf, &duprule->data.keyfields, ctrl.list) {
+               list_del(&ckf->ctrl.list);
+               kfree(ckf);
+       }
+
+       list_for_each_entry_safe(caf, newcaf, &duprule->data.actionfields, ctrl.list) {
+               list_del(&caf->ctrl.list);
+               kfree(caf);
+       }
+
+       kfree(duprule);
+       return ERR_PTR(-ENOMEM);
 }
 
 static void vcap_apply_width(u8 *dst, int width, int bytes)
index c07f25e791c7633a7cd1f4c297976cb41e6bb451..fe4e166de8a0458ffa509f2238a45ae33920743a 100644 (file)
@@ -243,10 +243,9 @@ static void vcap_test_api_init(struct vcap_admin *admin)
 }
 
 /* Helper function to create a rule of a specific size */
-static struct vcap_rule *
-test_vcap_xn_rule_creator(struct kunit *test, int cid, enum vcap_user user,
-                         u16 priority,
-                         int id, int size, int expected_addr)
+static void test_vcap_xn_rule_creator(struct kunit *test, int cid,
+                                     enum vcap_user user, u16 priority,
+                                     int id, int size, int expected_addr)
 {
        struct vcap_rule *rule;
        struct vcap_rule_internal *ri;
@@ -311,7 +310,7 @@ test_vcap_xn_rule_creator(struct kunit *test, int cid, enum vcap_user user,
        ret = vcap_add_rule(rule);
        KUNIT_EXPECT_EQ(test, 0, ret);
        KUNIT_EXPECT_EQ(test, expected_addr, ri->addr);
-       return rule;
+       vcap_free_rule(rule);
 }
 
 /* Prepare testing rule deletion */
@@ -995,6 +994,16 @@ static void vcap_api_encode_rule_actionset_test(struct kunit *test)
        KUNIT_EXPECT_EQ(test, (u32)0x00000000, actwords[11]);
 }
 
+static void vcap_free_ckf(struct vcap_rule *rule)
+{
+       struct vcap_client_keyfield *ckf, *next_ckf;
+
+       list_for_each_entry_safe(ckf, next_ckf, &rule->keyfields, ctrl.list) {
+               list_del(&ckf->ctrl.list);
+               kfree(ckf);
+       }
+}
+
 static void vcap_api_rule_add_keyvalue_test(struct kunit *test)
 {
        struct vcap_admin admin = {
@@ -1027,6 +1036,7 @@ static void vcap_api_rule_add_keyvalue_test(struct kunit *test)
        KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, kf->ctrl.type);
        KUNIT_EXPECT_EQ(test, 0x0, kf->data.u1.value);
        KUNIT_EXPECT_EQ(test, 0x1, kf->data.u1.mask);
+       vcap_free_ckf(rule);
 
        INIT_LIST_HEAD(&rule->keyfields);
        ret = vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, VCAP_BIT_1);
@@ -1039,6 +1049,7 @@ static void vcap_api_rule_add_keyvalue_test(struct kunit *test)
        KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, kf->ctrl.type);
        KUNIT_EXPECT_EQ(test, 0x1, kf->data.u1.value);
        KUNIT_EXPECT_EQ(test, 0x1, kf->data.u1.mask);
+       vcap_free_ckf(rule);
 
        INIT_LIST_HEAD(&rule->keyfields);
        ret = vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
@@ -1052,6 +1063,7 @@ static void vcap_api_rule_add_keyvalue_test(struct kunit *test)
        KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, kf->ctrl.type);
        KUNIT_EXPECT_EQ(test, 0x0, kf->data.u1.value);
        KUNIT_EXPECT_EQ(test, 0x0, kf->data.u1.mask);
+       vcap_free_ckf(rule);
 
        INIT_LIST_HEAD(&rule->keyfields);
        ret = vcap_rule_add_key_u32(rule, VCAP_KF_TYPE, 0x98765432, 0xff00ffab);
@@ -1064,6 +1076,7 @@ static void vcap_api_rule_add_keyvalue_test(struct kunit *test)
        KUNIT_EXPECT_EQ(test, VCAP_FIELD_U32, kf->ctrl.type);
        KUNIT_EXPECT_EQ(test, 0x98765432, kf->data.u32.value);
        KUNIT_EXPECT_EQ(test, 0xff00ffab, kf->data.u32.mask);
+       vcap_free_ckf(rule);
 
        INIT_LIST_HEAD(&rule->keyfields);
        ret = vcap_rule_add_key_u128(rule, VCAP_KF_L3_IP6_SIP, &dip);
@@ -1078,6 +1091,18 @@ static void vcap_api_rule_add_keyvalue_test(struct kunit *test)
                KUNIT_EXPECT_EQ(test, dip.value[idx], kf->data.u128.value[idx]);
        for (idx = 0; idx < ARRAY_SIZE(dip.mask); ++idx)
                KUNIT_EXPECT_EQ(test, dip.mask[idx], kf->data.u128.mask[idx]);
+       vcap_free_ckf(rule);
+}
+
+static void vcap_free_caf(struct vcap_rule *rule)
+{
+       struct vcap_client_actionfield *caf, *next_caf;
+
+       list_for_each_entry_safe(caf, next_caf,
+                                &rule->actionfields, ctrl.list) {
+               list_del(&caf->ctrl.list);
+               kfree(caf);
+       }
 }
 
 static void vcap_api_rule_add_actionvalue_test(struct kunit *test)
@@ -1105,6 +1130,7 @@ static void vcap_api_rule_add_actionvalue_test(struct kunit *test)
        KUNIT_EXPECT_EQ(test, VCAP_AF_POLICE_ENA, af->ctrl.action);
        KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, af->ctrl.type);
        KUNIT_EXPECT_EQ(test, 0x0, af->data.u1.value);
+       vcap_free_caf(rule);
 
        INIT_LIST_HEAD(&rule->actionfields);
        ret = vcap_rule_add_action_bit(rule, VCAP_AF_POLICE_ENA, VCAP_BIT_1);
@@ -1116,6 +1142,7 @@ static void vcap_api_rule_add_actionvalue_test(struct kunit *test)
        KUNIT_EXPECT_EQ(test, VCAP_AF_POLICE_ENA, af->ctrl.action);
        KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, af->ctrl.type);
        KUNIT_EXPECT_EQ(test, 0x1, af->data.u1.value);
+       vcap_free_caf(rule);
 
        INIT_LIST_HEAD(&rule->actionfields);
        ret = vcap_rule_add_action_bit(rule, VCAP_AF_POLICE_ENA, VCAP_BIT_ANY);
@@ -1127,6 +1154,7 @@ static void vcap_api_rule_add_actionvalue_test(struct kunit *test)
        KUNIT_EXPECT_EQ(test, VCAP_AF_POLICE_ENA, af->ctrl.action);
        KUNIT_EXPECT_EQ(test, VCAP_FIELD_BIT, af->ctrl.type);
        KUNIT_EXPECT_EQ(test, 0x0, af->data.u1.value);
+       vcap_free_caf(rule);
 
        INIT_LIST_HEAD(&rule->actionfields);
        ret = vcap_rule_add_action_u32(rule, VCAP_AF_TYPE, 0x98765432);
@@ -1138,6 +1166,7 @@ static void vcap_api_rule_add_actionvalue_test(struct kunit *test)
        KUNIT_EXPECT_EQ(test, VCAP_AF_TYPE, af->ctrl.action);
        KUNIT_EXPECT_EQ(test, VCAP_FIELD_U32, af->ctrl.type);
        KUNIT_EXPECT_EQ(test, 0x98765432, af->data.u32.value);
+       vcap_free_caf(rule);
 
        INIT_LIST_HEAD(&rule->actionfields);
        ret = vcap_rule_add_action_u32(rule, VCAP_AF_MASK_MODE, 0xaabbccdd);
@@ -1149,6 +1178,7 @@ static void vcap_api_rule_add_actionvalue_test(struct kunit *test)
        KUNIT_EXPECT_EQ(test, VCAP_AF_MASK_MODE, af->ctrl.action);
        KUNIT_EXPECT_EQ(test, VCAP_FIELD_U32, af->ctrl.type);
        KUNIT_EXPECT_EQ(test, 0xaabbccdd, af->data.u32.value);
+       vcap_free_caf(rule);
 }
 
 static void vcap_api_rule_find_keyset_basic_test(struct kunit *test)
@@ -1408,6 +1438,10 @@ static void vcap_api_encode_rule_test(struct kunit *test)
        ret = list_empty(&is2_admin.rules);
        KUNIT_EXPECT_EQ(test, false, ret);
        KUNIT_EXPECT_EQ(test, 0, ret);
+
+       vcap_enable_lookups(&test_vctrl, &test_netdev, 0, 0,
+                           rule->cookie, false);
+
        vcap_free_rule(rule);
 
        /* Check that the rule has been freed: tricky to access since this
@@ -1418,6 +1452,8 @@ static void vcap_api_encode_rule_test(struct kunit *test)
        KUNIT_EXPECT_EQ(test, true, ret);
        ret = list_empty(&rule->actionfields);
        KUNIT_EXPECT_EQ(test, true, ret);
+
+       vcap_del_rule(&test_vctrl, &test_netdev, id);
 }
 
 static void vcap_api_set_rule_counter_test(struct kunit *test)
@@ -1561,6 +1597,11 @@ static void vcap_api_rule_insert_in_order_test(struct kunit *test)
        test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 20, 400, 6, 774);
        test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 30, 300, 3, 771);
        test_vcap_xn_rule_creator(test, 10000, VCAP_USER_QOS, 40, 200, 2, 768);
+
+       vcap_del_rule(&test_vctrl, &test_netdev, 200);
+       vcap_del_rule(&test_vctrl, &test_netdev, 300);
+       vcap_del_rule(&test_vctrl, &test_netdev, 400);
+       vcap_del_rule(&test_vctrl, &test_netdev, 500);
 }
 
 static void vcap_api_rule_insert_reverse_order_test(struct kunit *test)
@@ -1619,6 +1660,11 @@ static void vcap_api_rule_insert_reverse_order_test(struct kunit *test)
                ++idx;
        }
        KUNIT_EXPECT_EQ(test, 768, admin.last_used_addr);
+
+       vcap_del_rule(&test_vctrl, &test_netdev, 500);
+       vcap_del_rule(&test_vctrl, &test_netdev, 400);
+       vcap_del_rule(&test_vctrl, &test_netdev, 300);
+       vcap_del_rule(&test_vctrl, &test_netdev, 200);
 }
 
 static void vcap_api_rule_remove_at_end_test(struct kunit *test)
@@ -1819,6 +1865,9 @@ static void vcap_api_rule_remove_in_front_test(struct kunit *test)
        KUNIT_EXPECT_EQ(test, 786, test_init_start);
        KUNIT_EXPECT_EQ(test, 8, test_init_count);
        KUNIT_EXPECT_EQ(test, 794, admin.last_used_addr);
+
+       vcap_del_rule(&test_vctrl, &test_netdev, 200);
+       vcap_del_rule(&test_vctrl, &test_netdev, 300);
 }
 
 static struct kunit_case vcap_api_rule_remove_test_cases[] = {
index 6aac98bcb9f4b9f2e16503acc28590ce598779f4..aae4131f146a88fb9b447b80f2dd4617211bed64 100644 (file)
@@ -187,6 +187,7 @@ typedef void (*ionic_desc_cb)(struct ionic_queue *q,
                              struct ionic_desc_info *desc_info,
                              struct ionic_cq_info *cq_info, void *cb_arg);
 
+#define IONIC_MAX_BUF_LEN                      ((u16)-1)
 #define IONIC_PAGE_SIZE                                PAGE_SIZE
 #define IONIC_PAGE_SPLIT_SZ                    (PAGE_SIZE / 2)
 #define IONIC_PAGE_GFP_MASK                    (GFP_ATOMIC | __GFP_NOWARN |\
index 26798fc635dbddf04947fb585ab2df4e26c7452f..44466e8c5d77bb819e783135c33651af5f2b9e79 100644 (file)
@@ -207,7 +207,8 @@ static struct sk_buff *ionic_rx_frags(struct ionic_queue *q,
                        return NULL;
                }
 
-               frag_len = min_t(u16, len, IONIC_PAGE_SIZE - buf_info->page_offset);
+               frag_len = min_t(u16, len, min_t(u32, IONIC_MAX_BUF_LEN,
+                                                IONIC_PAGE_SIZE - buf_info->page_offset));
                len -= frag_len;
 
                dma_sync_single_for_cpu(dev,
@@ -452,7 +453,8 @@ void ionic_rx_fill(struct ionic_queue *q)
 
                /* fill main descriptor - buf[0] */
                desc->addr = cpu_to_le64(buf_info->dma_addr + buf_info->page_offset);
-               frag_len = min_t(u16, len, IONIC_PAGE_SIZE - buf_info->page_offset);
+               frag_len = min_t(u16, len, min_t(u32, IONIC_MAX_BUF_LEN,
+                                                IONIC_PAGE_SIZE - buf_info->page_offset));
                desc->len = cpu_to_le16(frag_len);
                remain_len -= frag_len;
                buf_info++;
@@ -471,7 +473,9 @@ void ionic_rx_fill(struct ionic_queue *q)
                        }
 
                        sg_elem->addr = cpu_to_le64(buf_info->dma_addr + buf_info->page_offset);
-                       frag_len = min_t(u16, remain_len, IONIC_PAGE_SIZE - buf_info->page_offset);
+                       frag_len = min_t(u16, remain_len, min_t(u32, IONIC_MAX_BUF_LEN,
+                                                               IONIC_PAGE_SIZE -
+                                                               buf_info->page_offset));
                        sg_elem->len = cpu_to_le16(frag_len);
                        remain_len -= frag_len;
                        buf_info++;
index 6083b1c8e4fb9ad3c8f890678f12a5126da4269a..ea9186178091d5165ffcf14f5231a84d990a8e61 100644 (file)
@@ -799,6 +799,7 @@ static int rswitch_poll(struct napi_struct *napi, int budget)
        struct net_device *ndev = napi->dev;
        struct rswitch_private *priv;
        struct rswitch_device *rdev;
+       unsigned long flags;
        int quota = budget;
 
        rdev = netdev_priv(ndev);
@@ -816,10 +817,12 @@ retry:
 
        netif_wake_subqueue(ndev, 0);
 
-       napi_complete(napi);
-
-       rswitch_enadis_data_irq(priv, rdev->tx_queue->index, true);
-       rswitch_enadis_data_irq(priv, rdev->rx_queue->index, true);
+       if (napi_complete_done(napi, budget - quota)) {
+               spin_lock_irqsave(&priv->lock, flags);
+               rswitch_enadis_data_irq(priv, rdev->tx_queue->index, true);
+               rswitch_enadis_data_irq(priv, rdev->rx_queue->index, true);
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
 
 out:
        return budget - quota;
@@ -835,8 +838,10 @@ static void rswitch_queue_interrupt(struct net_device *ndev)
        struct rswitch_device *rdev = netdev_priv(ndev);
 
        if (napi_schedule_prep(&rdev->napi)) {
+               spin_lock(&rdev->priv->lock);
                rswitch_enadis_data_irq(rdev->priv, rdev->tx_queue->index, false);
                rswitch_enadis_data_irq(rdev->priv, rdev->rx_queue->index, false);
+               spin_unlock(&rdev->priv->lock);
                __napi_schedule(&rdev->napi);
        }
 }
@@ -1440,14 +1445,17 @@ static void rswitch_ether_port_deinit_all(struct rswitch_private *priv)
 static int rswitch_open(struct net_device *ndev)
 {
        struct rswitch_device *rdev = netdev_priv(ndev);
+       unsigned long flags;
 
        phy_start(ndev->phydev);
 
        napi_enable(&rdev->napi);
        netif_start_queue(ndev);
 
+       spin_lock_irqsave(&rdev->priv->lock, flags);
        rswitch_enadis_data_irq(rdev->priv, rdev->tx_queue->index, true);
        rswitch_enadis_data_irq(rdev->priv, rdev->rx_queue->index, true);
+       spin_unlock_irqrestore(&rdev->priv->lock, flags);
 
        if (bitmap_empty(rdev->priv->opened_ports, RSWITCH_NUM_PORTS))
                iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDIE);
@@ -1461,6 +1469,7 @@ static int rswitch_stop(struct net_device *ndev)
 {
        struct rswitch_device *rdev = netdev_priv(ndev);
        struct rswitch_gwca_ts_info *ts_info, *ts_info2;
+       unsigned long flags;
 
        netif_tx_stop_all_queues(ndev);
        bitmap_clear(rdev->priv->opened_ports, rdev->port, 1);
@@ -1476,8 +1485,10 @@ static int rswitch_stop(struct net_device *ndev)
                kfree(ts_info);
        }
 
+       spin_lock_irqsave(&rdev->priv->lock, flags);
        rswitch_enadis_data_irq(rdev->priv, rdev->tx_queue->index, false);
        rswitch_enadis_data_irq(rdev->priv, rdev->rx_queue->index, false);
+       spin_unlock_irqrestore(&rdev->priv->lock, flags);
 
        phy_stop(ndev->phydev);
        napi_disable(&rdev->napi);
@@ -1887,6 +1898,7 @@ static int renesas_eth_sw_probe(struct platform_device *pdev)
        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
+       spin_lock_init(&priv->lock);
 
        attr = soc_device_match(rswitch_soc_no_speed_change);
        if (attr)
index 54f397effbc6b1ee17f669f6411776634a4ff586..f0c16a37ea55858002a51a4984e77a34dd94e512 100644 (file)
@@ -1011,6 +1011,8 @@ struct rswitch_private {
        struct rswitch_etha etha[RSWITCH_NUM_PORTS];
        struct rswitch_mfwd mfwd;
 
+       spinlock_t lock;        /* lock interrupt registers' control */
+
        bool etha_no_runtime_change;
        bool gwca_halt;
 };
index 047322b04d4f52725c01a3db3e3e3788f9fb5e02..834f000ba1c49e6b192a2d34068e1d299e5ff6a8 100644 (file)
@@ -136,6 +136,8 @@ static struct efx_tc_mac_pedit_action *efx_tc_flower_get_mac(struct efx_nic *efx
        if (old) {
                /* don't need our new entry */
                kfree(ped);
+               if (IS_ERR(old)) /* oh dear, it's actually an error */
+                       return ERR_CAST(old);
                if (!refcount_inc_not_zero(&old->ref))
                        return ERR_PTR(-EAGAIN);
                /* existing entry found, ref taken */
@@ -602,6 +604,8 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx,
                kfree(encap);
                if (pseudo) /* don't need our new pseudo either */
                        efx_tc_flower_release_encap_match(efx, pseudo);
+               if (IS_ERR(old)) /* oh dear, it's actually an error */
+                       return PTR_ERR(old);
                /* check old and new em_types are compatible */
                switch (old->type) {
                case EFX_TC_EM_DIRECT:
@@ -700,6 +704,8 @@ static struct efx_tc_recirc_id *efx_tc_get_recirc_id(struct efx_nic *efx,
        if (old) {
                /* don't need our new entry */
                kfree(rid);
+               if (IS_ERR(old)) /* oh dear, it's actually an error */
+                       return ERR_CAST(old);
                if (!refcount_inc_not_zero(&old->ref))
                        return ERR_PTR(-EAGAIN);
                /* existing entry found */
@@ -1482,7 +1488,10 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx,
        old = rhashtable_lookup_get_insert_fast(&efx->tc->match_action_ht,
                                                &rule->linkage,
                                                efx_tc_match_action_ht_params);
-       if (old) {
+       if (IS_ERR(old)) {
+               rc = PTR_ERR(old);
+               goto release;
+       } else if (old) {
                netif_dbg(efx, drv, efx->net_dev,
                          "Ignoring already-offloaded rule (cookie %lx)\n",
                          tc->cookie);
@@ -1697,7 +1706,10 @@ static int efx_tc_flower_replace_lhs(struct efx_nic *efx,
        old = rhashtable_lookup_get_insert_fast(&efx->tc->lhs_rule_ht,
                                                &rule->linkage,
                                                efx_tc_lhs_rule_ht_params);
-       if (old) {
+       if (IS_ERR(old)) {
+               rc = PTR_ERR(old);
+               goto release;
+       } else if (old) {
                netif_dbg(efx, drv, efx->net_dev,
                          "Already offloaded rule (cookie %lx)\n", tc->cookie);
                rc = -EEXIST;
@@ -1858,7 +1870,10 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
        old = rhashtable_lookup_get_insert_fast(&efx->tc->match_action_ht,
                                                &rule->linkage,
                                                efx_tc_match_action_ht_params);
-       if (old) {
+       if (IS_ERR(old)) {
+               rc = PTR_ERR(old);
+               goto release;
+       } else if (old) {
                netif_dbg(efx, drv, efx->net_dev,
                          "Already offloaded rule (cookie %lx)\n", tc->cookie);
                NL_SET_ERR_MSG_MOD(extack, "Rule already offloaded");
index 8e06bfbcbea17cc5c3984d37a41725e61c895433..44bb57670340dae06cad31fde1deaa60a1ae6e90 100644 (file)
@@ -298,7 +298,10 @@ static int efx_tc_ct_replace(struct efx_tc_ct_zone *ct_zone,
        old = rhashtable_lookup_get_insert_fast(&efx->tc->ct_ht,
                                                &conn->linkage,
                                                efx_tc_ct_ht_params);
-       if (old) {
+       if (IS_ERR(old)) {
+               rc = PTR_ERR(old);
+               goto release;
+       } else if (old) {
                netif_dbg(efx, drv, efx->net_dev,
                          "Already offloaded conntrack (cookie %lx)\n", tc->cookie);
                rc = -EEXIST;
@@ -482,6 +485,8 @@ struct efx_tc_ct_zone *efx_tc_ct_register_zone(struct efx_nic *efx, u16 zone,
        if (old) {
                /* don't need our new entry */
                kfree(ct_zone);
+               if (IS_ERR(old)) /* oh dear, it's actually an error */
+                       return ERR_CAST(old);
                if (!refcount_inc_not_zero(&old->ref))
                        return ERR_PTR(-EAGAIN);
                /* existing entry found */
index 0fafb47ea0824b450de43520430e41816aab9d12..c4408842432363d02bcbd64d5ab4807a444ae15e 100644 (file)
@@ -236,6 +236,8 @@ struct efx_tc_counter_index *efx_tc_flower_get_counter_index(
        if (old) {
                /* don't need our new entry */
                kfree(ctr);
+               if (IS_ERR(old)) /* oh dear, it's actually an error */
+                       return ERR_CAST(old);
                if (!refcount_inc_not_zero(&old->ref))
                        return ERR_PTR(-EAGAIN);
                /* existing entry found */
index 7e8bcdb222ad18b4f175d5312613402d169dfbcd..87443f9dfd22b8b82564efc31bb0d8497d3757a1 100644 (file)
@@ -132,6 +132,8 @@ static int efx_bind_neigh(struct efx_nic *efx,
                /* don't need our new entry */
                put_net_track(neigh->net, &neigh->ns_tracker);
                kfree(neigh);
+               if (IS_ERR(old)) /* oh dear, it's actually an error */
+                       return PTR_ERR(old);
                if (!refcount_inc_not_zero(&old->ref))
                        return -EAGAIN;
                /* existing entry found, ref taken */
@@ -640,6 +642,8 @@ struct efx_tc_encap_action *efx_tc_flower_create_encap_md(
        if (old) {
                /* don't need our new entry */
                kfree(encap);
+               if (IS_ERR(old)) /* oh dear, it's actually an error */
+                       return ERR_CAST(old);
                if (!refcount_inc_not_zero(&old->ref))
                        return ERR_PTR(-EAGAIN);
                /* existing entry found, ref taken */
index 403cb397d4d36ca6c841b19efb733468422616cf..1e996c29043dcbdc40bfb1e030f93b70d989e4a4 100644 (file)
@@ -70,7 +70,7 @@ struct stmmac_txq_stats {
        u64 tx_tso_frames;
        u64 tx_tso_nfrags;
        struct u64_stats_sync syncp;
-};
+} ____cacheline_aligned_in_smp;
 
 struct stmmac_rxq_stats {
        u64 rx_bytes;
@@ -79,7 +79,7 @@ struct stmmac_rxq_stats {
        u64 rx_normal_irq_n;
        u64 napi_poll;
        struct u64_stats_sync syncp;
-};
+} ____cacheline_aligned_in_smp;
 
 /* Extra statistic and debug information exposed by ethtool */
 struct stmmac_extra_stats {
@@ -202,6 +202,9 @@ struct stmmac_extra_stats {
        unsigned long mtl_est_hlbf;
        unsigned long mtl_est_btre;
        unsigned long mtl_est_btrlm;
+       /* per queue statistics */
+       struct stmmac_txq_stats txq_stats[MTL_MAX_TX_QUEUES];
+       struct stmmac_rxq_stats rxq_stats[MTL_MAX_RX_QUEUES];
        unsigned long rx_dropped;
        unsigned long rx_errors;
        unsigned long tx_dropped;
index 01e77368eef1c1845b3c9b8fb610b62d61bd84dc..465ff1fd478554963cf339999c1768825b81aa97 100644 (file)
@@ -441,8 +441,8 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv,
                                     struct stmmac_extra_stats *x, u32 chan,
                                     u32 dir)
 {
-       struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan];
-       struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan];
+       struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
+       struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
        int ret = 0;
        u32 v;
 
@@ -455,9 +455,9 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv,
 
        if (v & EMAC_TX_INT) {
                ret |= handle_tx;
-               u64_stats_update_begin(&tx_q->txq_stats.syncp);
-               tx_q->txq_stats.tx_normal_irq_n++;
-               u64_stats_update_end(&tx_q->txq_stats.syncp);
+               u64_stats_update_begin(&txq_stats->syncp);
+               txq_stats->tx_normal_irq_n++;
+               u64_stats_update_end(&txq_stats->syncp);
        }
 
        if (v & EMAC_TX_DMA_STOP_INT)
@@ -479,9 +479,9 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv,
 
        if (v & EMAC_RX_INT) {
                ret |= handle_rx;
-               u64_stats_update_begin(&rx_q->rxq_stats.syncp);
-               rx_q->rxq_stats.rx_normal_irq_n++;
-               u64_stats_update_end(&rx_q->rxq_stats.syncp);
+               u64_stats_update_begin(&rxq_stats->syncp);
+               rxq_stats->rx_normal_irq_n++;
+               u64_stats_update_end(&rxq_stats->syncp);
        }
 
        if (v & EMAC_RX_BUF_UA_INT)
index 980e5f8a37ec520ebb4116e812b2cd70afa1c22f..9470d3fd2dede2bb436c05f6a92d87824c2db733 100644 (file)
@@ -171,8 +171,8 @@ int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
        const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
        u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(dwmac4_addrs, chan));
        u32 intr_en = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
-       struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan];
-       struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan];
+       struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
+       struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
        int ret = 0;
 
        if (dir == DMA_DIR_RX)
@@ -201,15 +201,15 @@ int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
        }
        /* TX/RX NORMAL interrupts */
        if (likely(intr_status & DMA_CHAN_STATUS_RI)) {
-               u64_stats_update_begin(&rx_q->rxq_stats.syncp);
-               rx_q->rxq_stats.rx_normal_irq_n++;
-               u64_stats_update_end(&rx_q->rxq_stats.syncp);
+               u64_stats_update_begin(&rxq_stats->syncp);
+               rxq_stats->rx_normal_irq_n++;
+               u64_stats_update_end(&rxq_stats->syncp);
                ret |= handle_rx;
        }
        if (likely(intr_status & DMA_CHAN_STATUS_TI)) {
-               u64_stats_update_begin(&tx_q->txq_stats.syncp);
-               tx_q->txq_stats.tx_normal_irq_n++;
-               u64_stats_update_end(&tx_q->txq_stats.syncp);
+               u64_stats_update_begin(&txq_stats->syncp);
+               txq_stats->tx_normal_irq_n++;
+               u64_stats_update_end(&txq_stats->syncp);
                ret |= handle_tx;
        }
 
index aaa09b16b016f21a12725f053296086ac21b0111..7907d62d343759d661e00452198ef8e6cfef3601 100644 (file)
@@ -162,8 +162,8 @@ static void show_rx_process_state(unsigned int status)
 int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
                        struct stmmac_extra_stats *x, u32 chan, u32 dir)
 {
-       struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan];
-       struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan];
+       struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
+       struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
        int ret = 0;
        /* read the status register (CSR5) */
        u32 intr_status = readl(ioaddr + DMA_STATUS);
@@ -215,16 +215,16 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
                        u32 value = readl(ioaddr + DMA_INTR_ENA);
                        /* to schedule NAPI on real RIE event. */
                        if (likely(value & DMA_INTR_ENA_RIE)) {
-                               u64_stats_update_begin(&rx_q->rxq_stats.syncp);
-                               rx_q->rxq_stats.rx_normal_irq_n++;
-                               u64_stats_update_end(&rx_q->rxq_stats.syncp);
+                               u64_stats_update_begin(&rxq_stats->syncp);
+                               rxq_stats->rx_normal_irq_n++;
+                               u64_stats_update_end(&rxq_stats->syncp);
                                ret |= handle_rx;
                        }
                }
                if (likely(intr_status & DMA_STATUS_TI)) {
-                       u64_stats_update_begin(&tx_q->txq_stats.syncp);
-                       tx_q->txq_stats.tx_normal_irq_n++;
-                       u64_stats_update_end(&tx_q->txq_stats.syncp);
+                       u64_stats_update_begin(&txq_stats->syncp);
+                       txq_stats->tx_normal_irq_n++;
+                       u64_stats_update_end(&txq_stats->syncp);
                        ret |= handle_tx;
                }
                if (unlikely(intr_status & DMA_STATUS_ERI))
index fa69d64a86943160449d6ac8012d82544104f126..3cde695fec91bd7592e23e725517f0cccee08a42 100644 (file)
@@ -337,8 +337,8 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv,
                                  struct stmmac_extra_stats *x, u32 chan,
                                  u32 dir)
 {
-       struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan];
-       struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan];
+       struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan];
+       struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];
        u32 intr_status = readl(ioaddr + XGMAC_DMA_CH_STATUS(chan));
        u32 intr_en = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));
        int ret = 0;
@@ -367,15 +367,15 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv,
        /* TX/RX NORMAL interrupts */
        if (likely(intr_status & XGMAC_NIS)) {
                if (likely(intr_status & XGMAC_RI)) {
-                       u64_stats_update_begin(&rx_q->rxq_stats.syncp);
-                       rx_q->rxq_stats.rx_normal_irq_n++;
-                       u64_stats_update_end(&rx_q->rxq_stats.syncp);
+                       u64_stats_update_begin(&rxq_stats->syncp);
+                       rxq_stats->rx_normal_irq_n++;
+                       u64_stats_update_end(&rxq_stats->syncp);
                        ret |= handle_rx;
                }
                if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) {
-                       u64_stats_update_begin(&tx_q->txq_stats.syncp);
-                       tx_q->txq_stats.tx_normal_irq_n++;
-                       u64_stats_update_end(&tx_q->txq_stats.syncp);
+                       u64_stats_update_begin(&txq_stats->syncp);
+                       txq_stats->tx_normal_irq_n++;
+                       u64_stats_update_end(&txq_stats->syncp);
                        ret |= handle_tx;
                }
        }
index 3401e888a9f6860b835a115a80102d01ea44ebff..cd7a9768de5f12960cd88167a5483fbc24cf06d8 100644 (file)
@@ -78,7 +78,6 @@ struct stmmac_tx_queue {
        dma_addr_t dma_tx_phy;
        dma_addr_t tx_tail_addr;
        u32 mss;
-       struct stmmac_txq_stats txq_stats;
 };
 
 struct stmmac_rx_buffer {
@@ -123,7 +122,6 @@ struct stmmac_rx_queue {
                unsigned int len;
                unsigned int error;
        } state;
-       struct stmmac_rxq_stats rxq_stats;
 };
 
 struct stmmac_channel {
index b7ac7abecdd3518001378039f63d9f0624bc9fd9..6aa5c0556d2203fcc2edd0307974f6e0d40ffccc 100644 (file)
@@ -548,14 +548,14 @@ static void stmmac_get_per_qstats(struct stmmac_priv *priv, u64 *data)
 
        pos = data;
        for (q = 0; q < tx_cnt; q++) {
-               struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[q];
+               struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[q];
                struct stmmac_txq_stats snapshot;
 
                data = pos;
                do {
-                       start = u64_stats_fetch_begin(&tx_q->txq_stats.syncp);
-                       snapshot = tx_q->txq_stats;
-               } while (u64_stats_fetch_retry(&tx_q->txq_stats.syncp, start));
+                       start = u64_stats_fetch_begin(&txq_stats->syncp);
+                       snapshot = *txq_stats;
+               } while (u64_stats_fetch_retry(&txq_stats->syncp, start));
 
                p = (char *)&snapshot + offsetof(struct stmmac_txq_stats, tx_pkt_n);
                for (stat = 0; stat < STMMAC_TXQ_STATS; stat++) {
@@ -566,14 +566,14 @@ static void stmmac_get_per_qstats(struct stmmac_priv *priv, u64 *data)
 
        pos = data;
        for (q = 0; q < rx_cnt; q++) {
-               struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[q];
+               struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[q];
                struct stmmac_rxq_stats snapshot;
 
                data = pos;
                do {
-                       start = u64_stats_fetch_begin(&rx_q->rxq_stats.syncp);
-                       snapshot = rx_q->rxq_stats;
-               } while (u64_stats_fetch_retry(&rx_q->rxq_stats.syncp, start));
+                       start = u64_stats_fetch_begin(&rxq_stats->syncp);
+                       snapshot = *rxq_stats;
+               } while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
 
                p = (char *)&snapshot + offsetof(struct stmmac_rxq_stats, rx_pkt_n);
                for (stat = 0; stat < STMMAC_RXQ_STATS; stat++) {
@@ -637,14 +637,14 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
 
        pos = j;
        for (i = 0; i < rx_queues_count; i++) {
-               struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[i];
+               struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[i];
                struct stmmac_rxq_stats snapshot;
 
                j = pos;
                do {
-                       start = u64_stats_fetch_begin(&rx_q->rxq_stats.syncp);
-                       snapshot = rx_q->rxq_stats;
-               } while (u64_stats_fetch_retry(&rx_q->rxq_stats.syncp, start));
+                       start = u64_stats_fetch_begin(&rxq_stats->syncp);
+                       snapshot = *rxq_stats;
+               } while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
 
                data[j++] += snapshot.rx_pkt_n;
                data[j++] += snapshot.rx_normal_irq_n;
@@ -654,14 +654,14 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
 
        pos = j;
        for (i = 0; i < tx_queues_count; i++) {
-               struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[i];
+               struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[i];
                struct stmmac_txq_stats snapshot;
 
                j = pos;
                do {
-                       start = u64_stats_fetch_begin(&tx_q->txq_stats.syncp);
-                       snapshot = tx_q->txq_stats;
-               } while (u64_stats_fetch_retry(&tx_q->txq_stats.syncp, start));
+                       start = u64_stats_fetch_begin(&txq_stats->syncp);
+                       snapshot = *txq_stats;
+               } while (u64_stats_fetch_retry(&txq_stats->syncp, start));
 
                data[j++] += snapshot.tx_pkt_n;
                data[j++] += snapshot.tx_normal_irq_n;
index 9a3182b9e767c566e2b0f89a0d21e74fb56e06af..83c567a89a46138544d23a1139345e87a7cd051a 100644 (file)
@@ -2426,6 +2426,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
 {
        struct netdev_queue *nq = netdev_get_tx_queue(priv->dev, queue);
        struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue];
+       struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[queue];
        struct xsk_buff_pool *pool = tx_q->xsk_pool;
        unsigned int entry = tx_q->cur_tx;
        struct dma_desc *tx_desc = NULL;
@@ -2505,9 +2506,9 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
                tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, priv->dma_conf.dma_tx_size);
                entry = tx_q->cur_tx;
        }
-       flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp);
-       tx_q->txq_stats.tx_set_ic_bit += tx_set_ic_bit;
-       u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags);
+       flags = u64_stats_update_begin_irqsave(&txq_stats->syncp);
+       txq_stats->tx_set_ic_bit += tx_set_ic_bit;
+       u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
 
        if (tx_desc) {
                stmmac_flush_tx_descriptors(priv, queue);
@@ -2547,6 +2548,7 @@ static void stmmac_bump_dma_threshold(struct stmmac_priv *priv, u32 chan)
 static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue)
 {
        struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue];
+       struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[queue];
        unsigned int bytes_compl = 0, pkts_compl = 0;
        unsigned int entry, xmits = 0, count = 0;
        u32 tx_packets = 0, tx_errors = 0;
@@ -2704,15 +2706,13 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue)
 
        /* We still have pending packets, let's call for a new scheduling */
        if (tx_q->dirty_tx != tx_q->cur_tx)
-               hrtimer_start(&tx_q->txtimer,
-                             STMMAC_COAL_TIMER(priv->tx_coal_timer[queue]),
-                             HRTIMER_MODE_REL);
+               stmmac_tx_timer_arm(priv, queue);
 
-       flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp);
-       tx_q->txq_stats.tx_packets += tx_packets;
-       tx_q->txq_stats.tx_pkt_n += tx_packets;
-       tx_q->txq_stats.tx_clean++;
-       u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags);
+       flags = u64_stats_update_begin_irqsave(&txq_stats->syncp);
+       txq_stats->tx_packets += tx_packets;
+       txq_stats->tx_pkt_n += tx_packets;
+       txq_stats->tx_clean++;
+       u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
 
        priv->xstats.tx_errors += tx_errors;
 
@@ -2995,9 +2995,13 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
 static void stmmac_tx_timer_arm(struct stmmac_priv *priv, u32 queue)
 {
        struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue];
+       u32 tx_coal_timer = priv->tx_coal_timer[queue];
+
+       if (!tx_coal_timer)
+               return;
 
        hrtimer_start(&tx_q->txtimer,
-                     STMMAC_COAL_TIMER(priv->tx_coal_timer[queue]),
+                     STMMAC_COAL_TIMER(tx_coal_timer),
                      HRTIMER_MODE_REL);
 }
 
@@ -4112,6 +4116,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
        int nfrags = skb_shinfo(skb)->nr_frags;
        u32 queue = skb_get_queue_mapping(skb);
        unsigned int first_entry, tx_packets;
+       struct stmmac_txq_stats *txq_stats;
        int tmp_pay_len = 0, first_tx;
        struct stmmac_tx_queue *tx_q;
        bool has_vlan, set_ic;
@@ -4122,6 +4127,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
        int i;
 
        tx_q = &priv->dma_conf.tx_queue[queue];
+       txq_stats = &priv->xstats.txq_stats[queue];
        first_tx = tx_q->cur_tx;
 
        /* Compute header lengths */
@@ -4280,13 +4286,13 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
                netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue));
        }
 
-       flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp);
-       tx_q->txq_stats.tx_bytes += skb->len;
-       tx_q->txq_stats.tx_tso_frames++;
-       tx_q->txq_stats.tx_tso_nfrags += nfrags;
+       flags = u64_stats_update_begin_irqsave(&txq_stats->syncp);
+       txq_stats->tx_bytes += skb->len;
+       txq_stats->tx_tso_frames++;
+       txq_stats->tx_tso_nfrags += nfrags;
        if (set_ic)
-               tx_q->txq_stats.tx_set_ic_bit++;
-       u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags);
+               txq_stats->tx_set_ic_bit++;
+       u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
 
        if (priv->sarc_type)
                stmmac_set_desc_sarc(priv, first, priv->sarc_type);
@@ -4357,6 +4363,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
        u32 queue = skb_get_queue_mapping(skb);
        int nfrags = skb_shinfo(skb)->nr_frags;
        int gso = skb_shinfo(skb)->gso_type;
+       struct stmmac_txq_stats *txq_stats;
        struct dma_edesc *tbs_desc = NULL;
        struct dma_desc *desc, *first;
        struct stmmac_tx_queue *tx_q;
@@ -4366,6 +4373,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
        dma_addr_t des;
 
        tx_q = &priv->dma_conf.tx_queue[queue];
+       txq_stats = &priv->xstats.txq_stats[queue];
        first_tx = tx_q->cur_tx;
 
        if (priv->tx_path_in_lpi_mode && priv->eee_sw_timer_en)
@@ -4517,11 +4525,11 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
                netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue));
        }
 
-       flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp);
-       tx_q->txq_stats.tx_bytes += skb->len;
+       flags = u64_stats_update_begin_irqsave(&txq_stats->syncp);
+       txq_stats->tx_bytes += skb->len;
        if (set_ic)
-               tx_q->txq_stats.tx_set_ic_bit++;
-       u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags);
+               txq_stats->tx_set_ic_bit++;
+       u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
 
        if (priv->sarc_type)
                stmmac_set_desc_sarc(priv, first, priv->sarc_type);
@@ -4728,6 +4736,7 @@ static unsigned int stmmac_rx_buf2_len(struct stmmac_priv *priv,
 static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
                                struct xdp_frame *xdpf, bool dma_map)
 {
+       struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[queue];
        struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue];
        unsigned int entry = tx_q->cur_tx;
        struct dma_desc *tx_desc;
@@ -4787,9 +4796,9 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
                unsigned long flags;
                tx_q->tx_count_frames = 0;
                stmmac_set_tx_ic(priv, tx_desc);
-               flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp);
-               tx_q->txq_stats.tx_set_ic_bit++;
-               u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags);
+               flags = u64_stats_update_begin_irqsave(&txq_stats->syncp);
+               txq_stats->tx_set_ic_bit++;
+               u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
        }
 
        stmmac_enable_dma_transmission(priv, priv->ioaddr);
@@ -4934,7 +4943,7 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue,
                                   struct dma_desc *p, struct dma_desc *np,
                                   struct xdp_buff *xdp)
 {
-       struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue];
+       struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[queue];
        struct stmmac_channel *ch = &priv->channel[queue];
        unsigned int len = xdp->data_end - xdp->data;
        enum pkt_hash_types hash_type;
@@ -4964,10 +4973,10 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue,
        skb_record_rx_queue(skb, queue);
        napi_gro_receive(&ch->rxtx_napi, skb);
 
-       flags = u64_stats_update_begin_irqsave(&rx_q->rxq_stats.syncp);
-       rx_q->rxq_stats.rx_pkt_n++;
-       rx_q->rxq_stats.rx_bytes += len;
-       u64_stats_update_end_irqrestore(&rx_q->rxq_stats.syncp, flags);
+       flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp);
+       rxq_stats->rx_pkt_n++;
+       rxq_stats->rx_bytes += len;
+       u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags);
 }
 
 static bool stmmac_rx_refill_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
@@ -5040,6 +5049,7 @@ static struct stmmac_xdp_buff *xsk_buff_to_stmmac_ctx(struct xdp_buff *xdp)
 
 static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue)
 {
+       struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[queue];
        struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue];
        unsigned int count = 0, error = 0, len = 0;
        int dirty = stmmac_rx_dirty(priv, queue);
@@ -5203,9 +5213,9 @@ read_again:
 
        stmmac_finalize_xdp_rx(priv, xdp_status);
 
-       flags = u64_stats_update_begin_irqsave(&rx_q->rxq_stats.syncp);
-       rx_q->rxq_stats.rx_pkt_n += count;
-       u64_stats_update_end_irqrestore(&rx_q->rxq_stats.syncp, flags);
+       flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp);
+       rxq_stats->rx_pkt_n += count;
+       u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags);
 
        priv->xstats.rx_dropped += rx_dropped;
        priv->xstats.rx_errors += rx_errors;
@@ -5233,6 +5243,7 @@ read_again:
 static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
 {
        u32 rx_errors = 0, rx_dropped = 0, rx_bytes = 0, rx_packets = 0;
+       struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[queue];
        struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue];
        struct stmmac_channel *ch = &priv->channel[queue];
        unsigned int count = 0, error = 0, len = 0;
@@ -5494,11 +5505,11 @@ drain_data:
 
        stmmac_rx_refill(priv, queue);
 
-       flags = u64_stats_update_begin_irqsave(&rx_q->rxq_stats.syncp);
-       rx_q->rxq_stats.rx_packets += rx_packets;
-       rx_q->rxq_stats.rx_bytes += rx_bytes;
-       rx_q->rxq_stats.rx_pkt_n += count;
-       u64_stats_update_end_irqrestore(&rx_q->rxq_stats.syncp, flags);
+       flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp);
+       rxq_stats->rx_packets += rx_packets;
+       rxq_stats->rx_bytes += rx_bytes;
+       rxq_stats->rx_pkt_n += count;
+       u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags);
 
        priv->xstats.rx_dropped += rx_dropped;
        priv->xstats.rx_errors += rx_errors;
@@ -5511,15 +5522,15 @@ static int stmmac_napi_poll_rx(struct napi_struct *napi, int budget)
        struct stmmac_channel *ch =
                container_of(napi, struct stmmac_channel, rx_napi);
        struct stmmac_priv *priv = ch->priv_data;
-       struct stmmac_rx_queue *rx_q;
+       struct stmmac_rxq_stats *rxq_stats;
        u32 chan = ch->index;
        unsigned long flags;
        int work_done;
 
-       rx_q = &priv->dma_conf.rx_queue[chan];
-       flags = u64_stats_update_begin_irqsave(&rx_q->rxq_stats.syncp);
-       rx_q->rxq_stats.napi_poll++;
-       u64_stats_update_end_irqrestore(&rx_q->rxq_stats.syncp, flags);
+       rxq_stats = &priv->xstats.rxq_stats[chan];
+       flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp);
+       rxq_stats->napi_poll++;
+       u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags);
 
        work_done = stmmac_rx(priv, budget, chan);
        if (work_done < budget && napi_complete_done(napi, work_done)) {
@@ -5538,15 +5549,15 @@ static int stmmac_napi_poll_tx(struct napi_struct *napi, int budget)
        struct stmmac_channel *ch =
                container_of(napi, struct stmmac_channel, tx_napi);
        struct stmmac_priv *priv = ch->priv_data;
-       struct stmmac_tx_queue *tx_q;
+       struct stmmac_txq_stats *txq_stats;
        u32 chan = ch->index;
        unsigned long flags;
        int work_done;
 
-       tx_q = &priv->dma_conf.tx_queue[chan];
-       flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp);
-       tx_q->txq_stats.napi_poll++;
-       u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags);
+       txq_stats = &priv->xstats.txq_stats[chan];
+       flags = u64_stats_update_begin_irqsave(&txq_stats->syncp);
+       txq_stats->napi_poll++;
+       u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
 
        work_done = stmmac_tx_clean(priv, budget, chan);
        work_done = min(work_done, budget);
@@ -5568,20 +5579,20 @@ static int stmmac_napi_poll_rxtx(struct napi_struct *napi, int budget)
                container_of(napi, struct stmmac_channel, rxtx_napi);
        struct stmmac_priv *priv = ch->priv_data;
        int rx_done, tx_done, rxtx_done;
-       struct stmmac_rx_queue *rx_q;
-       struct stmmac_tx_queue *tx_q;
+       struct stmmac_rxq_stats *rxq_stats;
+       struct stmmac_txq_stats *txq_stats;
        u32 chan = ch->index;
        unsigned long flags;
 
-       rx_q = &priv->dma_conf.rx_queue[chan];
-       flags = u64_stats_update_begin_irqsave(&rx_q->rxq_stats.syncp);
-       rx_q->rxq_stats.napi_poll++;
-       u64_stats_update_end_irqrestore(&rx_q->rxq_stats.syncp, flags);
+       rxq_stats = &priv->xstats.rxq_stats[chan];
+       flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp);
+       rxq_stats->napi_poll++;
+       u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags);
 
-       tx_q = &priv->dma_conf.tx_queue[chan];
-       flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp);
-       tx_q->txq_stats.napi_poll++;
-       u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags);
+       txq_stats = &priv->xstats.txq_stats[chan];
+       flags = u64_stats_update_begin_irqsave(&txq_stats->syncp);
+       txq_stats->napi_poll++;
+       u64_stats_update_end_irqrestore(&txq_stats->syncp, flags);
 
        tx_done = stmmac_tx_clean(priv, budget, chan);
        tx_done = min(tx_done, budget);
@@ -6924,7 +6935,7 @@ static void stmmac_get_stats64(struct net_device *dev, struct rtnl_link_stats64
        int q;
 
        for (q = 0; q < tx_cnt; q++) {
-               struct stmmac_txq_stats *txq_stats = &priv->dma_conf.tx_queue[q].txq_stats;
+               struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[q];
                u64 tx_packets;
                u64 tx_bytes;
 
@@ -6939,7 +6950,7 @@ static void stmmac_get_stats64(struct net_device *dev, struct rtnl_link_stats64
        }
 
        for (q = 0; q < rx_cnt; q++) {
-               struct stmmac_rxq_stats *rxq_stats = &priv->dma_conf.rx_queue[q].rxq_stats;
+               struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[q];
                u64 rx_packets;
                u64 rx_bytes;
 
@@ -7340,9 +7351,9 @@ int stmmac_dvr_probe(struct device *device,
        priv->dev = ndev;
 
        for (i = 0; i < MTL_MAX_RX_QUEUES; i++)
-               u64_stats_init(&priv->dma_conf.rx_queue[i].rxq_stats.syncp);
+               u64_stats_init(&priv->xstats.rxq_stats[i].syncp);
        for (i = 0; i < MTL_MAX_TX_QUEUES; i++)
-               u64_stats_init(&priv->dma_conf.tx_queue[i].txq_stats.syncp);
+               u64_stats_init(&priv->xstats.txq_stats[i].syncp);
 
        stmmac_set_ethtool_ops(ndev);
        priv->pause = pause;
index 88b5b1b47779a54c6970bc29bac47bfe35c35fbe..0a3346650e03117ba0e1ba8df98cfaf4024c5c67 100644 (file)
@@ -199,6 +199,7 @@ config TI_ICSSG_PRUETH
 
 config TI_ICSS_IEP
        tristate "TI PRU ICSS IEP driver"
+       depends on PTP_1588_CLOCK_OPTIONAL
        depends on TI_PRUSS
        default TI_PRUSS
        help
index e8b94580194e719184527cf8d2fc9e138afdebb2..508d9a392ab182c4809019e73fd2b658fd1d66de 100644 (file)
@@ -2115,7 +2115,12 @@ static const struct ethtool_ops team_ethtool_ops = {
 static void team_setup_by_port(struct net_device *dev,
                               struct net_device *port_dev)
 {
-       dev->header_ops = port_dev->header_ops;
+       struct team *team = netdev_priv(dev);
+
+       if (port_dev->type == ARPHRD_ETHER)
+               dev->header_ops = team->header_ops_cache;
+       else
+               dev->header_ops = port_dev->header_ops;
        dev->type = port_dev->type;
        dev->hard_header_len = port_dev->hard_header_len;
        dev->needed_headroom = port_dev->needed_headroom;
@@ -2162,8 +2167,11 @@ static int team_dev_type_check_change(struct net_device *dev,
 
 static void team_setup(struct net_device *dev)
 {
+       struct team *team = netdev_priv(dev);
+
        ether_setup(dev);
        dev->max_mtu = ETH_MAX_MTU;
+       team->header_ops_cache = dev->header_ops;
 
        dev->netdev_ops = &team_netdev_ops;
        dev->ethtool_ops = &team_ethtool_ops;
index 0c1e8970ee589fde200ba494f79ed48ce499ae7a..0a53ec293d0408b591467baca93e1e1ff0999191 100644 (file)
@@ -1049,12 +1049,11 @@ static bool tbnet_xmit_csum_and_map(struct tbnet *net, struct sk_buff *skb,
                *tucso = ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
                                            ip_hdr(skb)->daddr, 0,
                                            ip_hdr(skb)->protocol, 0);
-       } else if (skb_is_gso_v6(skb)) {
+       } else if (skb_is_gso(skb) && skb_is_gso_v6(skb)) {
                tucso = dest + ((void *)&(tcp_hdr(skb)->check) - data);
                *tucso = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
                                          &ipv6_hdr(skb)->daddr, 0,
                                          IPPROTO_TCP, 0);
-               return false;
        } else if (protocol == htons(ETH_P_IPV6)) {
                tucso = dest + skb_checksum_start_offset(skb) + skb->csum_offset;
                *tucso = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
index 332c853ca99b30e2279df7d14d60d04055829a57..0c13d9950cd85502e35c1c26da43d95582a08314 100644 (file)
@@ -2636,6 +2636,9 @@ static int r8152_poll(struct napi_struct *napi, int budget)
        struct r8152 *tp = container_of(napi, struct r8152, napi);
        int work_done;
 
+       if (!budget)
+               return 0;
+
        work_done = rx_bottom(tp, budget);
 
        if (work_done < budget) {
index 9c6f4f83f22b0750cec1313a8746cb8c9dbcd7be..0deefd1573cf264e50a6451fd307c2174aef4d4c 100644 (file)
@@ -1446,6 +1446,8 @@ static int veth_open(struct net_device *dev)
                netif_carrier_on(peer);
        }
 
+       veth_set_xdp_features(dev);
+
        return 0;
 }
 
index e463f59e95c2535cef645939b156de7ae428ceb2..5b5597073b004c911f88b472748447804594c752 100644 (file)
@@ -4331,6 +4331,10 @@ static size_t vxlan_get_size(const struct net_device *dev)
                nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_TX */
                nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_RX */
                nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_LOCALBYPASS */
+               nla_total_size(0) + /* IFLA_VXLAN_GBP */
+               nla_total_size(0) + /* IFLA_VXLAN_GPE */
+               nla_total_size(0) + /* IFLA_VXLAN_REMCSUM_NOPARTIAL */
+               nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_VNIFILTER */
                0;
 }
 
index f3a01b79148cb1e3246d759cf0bdab809270eb2a..21783aa2ee8e18f64154f479a4b6800eccecde32 100644 (file)
@@ -2245,25 +2245,8 @@ int nvme_enable_ctrl(struct nvme_ctrl *ctrl)
        else
                ctrl->ctrl_config = NVME_CC_CSS_NVM;
 
-       if (ctrl->cap & NVME_CAP_CRMS_CRWMS) {
-               u32 crto;
-
-               ret = ctrl->ops->reg_read32(ctrl, NVME_REG_CRTO, &crto);
-               if (ret) {
-                       dev_err(ctrl->device, "Reading CRTO failed (%d)\n",
-                               ret);
-                       return ret;
-               }
-
-               if (ctrl->cap & NVME_CAP_CRMS_CRIMS) {
-                       ctrl->ctrl_config |= NVME_CC_CRIME;
-                       timeout = NVME_CRTO_CRIMT(crto);
-               } else {
-                       timeout = NVME_CRTO_CRWMT(crto);
-               }
-       } else {
-               timeout = NVME_CAP_TIMEOUT(ctrl->cap);
-       }
+       if (ctrl->cap & NVME_CAP_CRMS_CRWMS && ctrl->cap & NVME_CAP_CRMS_CRIMS)
+               ctrl->ctrl_config |= NVME_CC_CRIME;
 
        ctrl->ctrl_config |= (NVME_CTRL_PAGE_SHIFT - 12) << NVME_CC_MPS_SHIFT;
        ctrl->ctrl_config |= NVME_CC_AMS_RR | NVME_CC_SHN_NONE;
@@ -2277,6 +2260,39 @@ int nvme_enable_ctrl(struct nvme_ctrl *ctrl)
        if (ret)
                return ret;
 
+       /* CAP value may change after initial CC write */
+       ret = ctrl->ops->reg_read64(ctrl, NVME_REG_CAP, &ctrl->cap);
+       if (ret)
+               return ret;
+
+       timeout = NVME_CAP_TIMEOUT(ctrl->cap);
+       if (ctrl->cap & NVME_CAP_CRMS_CRWMS) {
+               u32 crto, ready_timeout;
+
+               ret = ctrl->ops->reg_read32(ctrl, NVME_REG_CRTO, &crto);
+               if (ret) {
+                       dev_err(ctrl->device, "Reading CRTO failed (%d)\n",
+                               ret);
+                       return ret;
+               }
+
+               /*
+                * CRTO should always be greater or equal to CAP.TO, but some
+                * devices are known to get this wrong. Use the larger of the
+                * two values.
+                */
+               if (ctrl->ctrl_config & NVME_CC_CRIME)
+                       ready_timeout = NVME_CRTO_CRIMT(crto);
+               else
+                       ready_timeout = NVME_CRTO_CRWMT(crto);
+
+               if (ready_timeout < timeout)
+                       dev_warn_once(ctrl->device, "bad crto:%x cap:%llx\n",
+                                     crto, ctrl->cap);
+               else
+                       timeout = ready_timeout;
+       }
+
        ctrl->ctrl_config |= NVME_CC_ENABLE;
        ret = ctrl->ops->reg_write32(ctrl, NVME_REG_CC, ctrl->ctrl_config);
        if (ret)
index 1cd2bf82319a988021cbb04d311ebee3dc017bed..a15b37750d6e931b0a875058cda6868034a642d9 100644 (file)
@@ -1924,7 +1924,7 @@ char *nvme_fc_io_getuuid(struct nvmefc_fcp_req *req)
        struct nvme_fc_fcp_op *op = fcp_req_to_fcp_op(req);
        struct request *rq = op->rq;
 
-       if (!IS_ENABLED(CONFIG_BLK_CGROUP_FC_APPID) || !rq->bio)
+       if (!IS_ENABLED(CONFIG_BLK_CGROUP_FC_APPID) || !rq || !rq->bio)
                return NULL;
        return blkcg_get_fc_appid(rq->bio);
 }
index 316f3e4ca7cc60da613e5f246f9e5a861d60e14f..8df73a0b3980cde3f150b66672db7965eda9a328 100644 (file)
@@ -187,7 +187,7 @@ static umode_t nvme_hwmon_is_visible(const void *_data,
        return 0;
 }
 
-static const struct hwmon_channel_info *nvme_hwmon_info[] = {
+static const struct hwmon_channel_info *const nvme_hwmon_info[] = {
        HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
        HWMON_CHANNEL_INFO(temp,
                           HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN |
index 2f57da12d9836dd1af3beceb4d61e9e73ceb5930..347cb5daebc3cedefc09dac49a10960f00aa1ead 100644 (file)
@@ -2916,9 +2916,6 @@ static struct nvme_dev *nvme_pci_alloc_dev(struct pci_dev *pdev,
        struct nvme_dev *dev;
        int ret = -ENOMEM;
 
-       if (node == NUMA_NO_NODE)
-               set_dev_node(&pdev->dev, first_memory_node);
-
        dev = kzalloc_node(sizeof(*dev), GFP_KERNEL, node);
        if (!dev)
                return ERR_PTR(-ENOMEM);
index 868aa4de2e4c4ef7bcfc3c704ae10791f1725ff9..cd92d7ddf5ed15f677d9d954a43d064659ce2a36 100644 (file)
@@ -348,7 +348,7 @@ static void nvmet_tcp_build_pdu_iovec(struct nvmet_tcp_cmd *cmd)
        while (length) {
                u32 iov_len = min_t(u32, length, sg->length - sg_offset);
 
-               bvec_set_page(iov, sg_page(sg), sg->length,
+               bvec_set_page(iov, sg_page(sg), iov_len,
                                sg->offset + sg_offset);
 
                length -= iov_len;
index 509a4072d50afd7560a63c06b27089480a5b5a0d..9ce0d20a6c581204bb4c10e4a11b10e03d3e17a2 100644 (file)
@@ -214,7 +214,7 @@ struct ioa_registers {
 struct ioc {
        struct ioa_registers __iomem *ioc_regs;  /* I/O MMU base address */
        u8  *res_map;                   /* resource map, bit == pdir entry */
-       u64 *pdir_base;                 /* physical base address */
+       __le64 *pdir_base;              /* physical base address */
        u32 pdir_size;                  /* bytes, function of IOV Space size */
        u32 res_hint;                   /* next available IOVP -
                                           circular search */
@@ -339,7 +339,7 @@ ccio_alloc_range(struct ioc *ioc, struct device *dev, size_t size)
        BUG_ON(pages_needed == 0);
        BUG_ON((pages_needed * IOVP_SIZE) > DMA_CHUNK_SIZE);
 
-       DBG_RES("%s() size: %d pages_needed %d\n",
+       DBG_RES("%s() size: %zu pages_needed %d\n",
                        __func__, size, pages_needed);
 
        /*
@@ -427,7 +427,7 @@ ccio_free_range(struct ioc *ioc, dma_addr_t iova, unsigned long pages_mapped)
        BUG_ON((pages_mapped * IOVP_SIZE) > DMA_CHUNK_SIZE);
        BUG_ON(pages_mapped > BITS_PER_LONG);
 
-       DBG_RES("%s():  res_idx: %d pages_mapped %d\n", 
+       DBG_RES("%s():  res_idx: %d pages_mapped %lu\n",
                __func__, res_idx, pages_mapped);
 
 #ifdef CCIO_COLLECT_STATS
@@ -543,7 +543,7 @@ static u32 hint_lookup[] = {
  * index are bits 12:19 of the value returned by LCI.
  */ 
 static void
-ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
+ccio_io_pdir_entry(__le64 *pdir_ptr, space_t sid, unsigned long vba,
                   unsigned long hints)
 {
        register unsigned long pa;
@@ -719,7 +719,7 @@ ccio_map_single(struct device *dev, void *addr, size_t size,
        unsigned long flags;
        dma_addr_t iovp;
        dma_addr_t offset;
-       u64 *pdir_start;
+       __le64 *pdir_start;
        unsigned long hint = hint_lookup[(int)direction];
 
        BUG_ON(!dev);
@@ -746,8 +746,8 @@ ccio_map_single(struct device *dev, void *addr, size_t size,
 
        pdir_start = &(ioc->pdir_base[idx]);
 
-       DBG_RUN("%s() 0x%p -> 0x%lx size: %0x%x\n",
-               __func__, addr, (long)iovp | offset, size);
+       DBG_RUN("%s() %px -> %#lx size: %zu\n",
+               __func__, addr, (long)(iovp | offset), size);
 
        /* If not cacheline aligned, force SAFE_DMA on the whole mess */
        if((size % L1_CACHE_BYTES) || ((unsigned long)addr % L1_CACHE_BYTES))
@@ -805,7 +805,7 @@ ccio_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
                return;
        }
 
-       DBG_RUN("%s() iovp 0x%lx/%x\n",
+       DBG_RUN("%s() iovp %#lx/%zx\n",
                __func__, (long)iova, size);
 
        iova ^= offset;        /* clear offset bits */
@@ -1283,7 +1283,7 @@ ccio_ioc_init(struct ioc *ioc)
                        iova_space_size>>20,
                        iov_order + PAGE_SHIFT);
 
-       ioc->pdir_base = (u64 *)__get_free_pages(GFP_KERNEL, 
+       ioc->pdir_base = (__le64 *)__get_free_pages(GFP_KERNEL,
                                                 get_order(ioc->pdir_size));
        if(NULL == ioc->pdir_base) {
                panic("%s() could not allocate I/O Page Table\n", __func__);
index 0905be256de087d016759f85f4df55046bf882ce..c43f1a212a5c806e66549f7ed5ae31582fa2ea7b 100644 (file)
 static inline unsigned int
 iommu_fill_pdir(struct ioc *ioc, struct scatterlist *startsg, int nents, 
                unsigned long hint,
-               void (*iommu_io_pdir_entry)(u64 *, space_t, unsigned long,
+               void (*iommu_io_pdir_entry)(__le64 *, space_t, unsigned long,
                                            unsigned long))
 {
        struct scatterlist *dma_sg = startsg;   /* pointer to current DMA */
        unsigned int n_mappings = 0;
        unsigned long dma_offset = 0, dma_len = 0;
-       u64 *pdirp = NULL;
+       __le64 *pdirp = NULL;
 
        /* Horrible hack.  For efficiency's sake, dma_sg starts one 
         * entry below the true start (it is immediately incremented
@@ -31,8 +31,8 @@ iommu_fill_pdir(struct ioc *ioc, struct scatterlist *startsg, int nents,
                unsigned long vaddr;
                long size;
 
-               DBG_RUN_SG(" %d : %08lx/%05x %p/%05x\n", nents,
-                          (unsigned long)sg_dma_address(startsg), cnt,
+               DBG_RUN_SG(" %d : %08lx %p/%05x\n", nents,
+                          (unsigned long)sg_dma_address(startsg),
                           sg_virt(startsg), startsg->length
                );
 
index a7df764f1a7224c1b8148051426035d3f31b73bb..a4011461189b6a225512390d3b99c42cc2635f9c 100644 (file)
@@ -202,9 +202,9 @@ static inline void iosapic_write(void __iomem *iosapic, unsigned int reg, u32 va
 
 static DEFINE_SPINLOCK(iosapic_lock);
 
-static inline void iosapic_eoi(void __iomem *addr, unsigned int data)
+static inline void iosapic_eoi(__le32 __iomem *addr, __le32 data)
 {
-       __raw_writel(data, addr);
+       __raw_writel((__force u32)data, addr);
 }
 
 /*
index 73ecc657ad954126455d9be9b62b62a2cdfdd764..bd8ff40162b4b9ed9715a97018c6c1d487908104 100644 (file)
@@ -118,8 +118,8 @@ struct iosapic_irt {
 struct vector_info {
        struct iosapic_info *iosapic;   /* I/O SAPIC this vector is on */
        struct irt_entry *irte;         /* IRT entry */
-       u32 __iomem *eoi_addr;          /* precalculate EOI reg address */
-       u32     eoi_data;               /* IA64: ?       PA: swapped txn_data */
+       __le32 __iomem *eoi_addr;       /* precalculate EOI reg address */
+       __le32  eoi_data;               /* IA64: ?       PA: swapped txn_data */
        int     txn_irq;                /* virtual IRQ number for processor */
        ulong   txn_addr;               /* IA64: id_eid  PA: partial HPA */
        u32     txn_data;               /* CPU interrupt bit */
index f6b5106753189e91127bdb184c0967783e5eacff..05e7103d1d407a97298bc68196ddde7ee4730283 100644 (file)
@@ -46,8 +46,6 @@
 #include <linux/module.h>
 
 #include <asm/ropes.h>
-#include <asm/mckinley.h>      /* for proc_mckinley_root */
-#include <asm/runway.h>                /* for proc_runway_root */
 #include <asm/page.h>          /* for PAGE0 */
 #include <asm/pdc.h>           /* for PDC_MODEL_* */
 #include <asm/pdcpat.h>                /* for is_pdc_pat() */
@@ -122,7 +120,7 @@ MODULE_PARM_DESC(sba_reserve_agpgart, "Reserve half of IO pdir as AGPGART");
 #endif
 
 static struct proc_dir_entry *proc_runway_root __ro_after_init;
-struct proc_dir_entry *proc_mckinley_root __ro_after_init;
+static struct proc_dir_entry *proc_mckinley_root __ro_after_init;
 
 /************************************
 ** SBA register read and write support
@@ -204,7 +202,7 @@ static void
 sba_dump_pdir_entry(struct ioc *ioc, char *msg, uint pide)
 {
        /* start printing from lowest pde in rval */
-       u64 *ptr = &(ioc->pdir_base[pide & (~0U * BITS_PER_LONG)]);
+       __le64 *ptr = &(ioc->pdir_base[pide & (~0U * BITS_PER_LONG)]);
        unsigned long *rptr = (unsigned long *) &(ioc->res_map[(pide >>3) & ~(sizeof(unsigned long) - 1)]);
        uint rcnt;
 
@@ -571,7 +569,7 @@ typedef unsigned long space_t;
  */
 
 static void
-sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
+sba_io_pdir_entry(__le64 *pdir_ptr, space_t sid, unsigned long vba,
                  unsigned long hint)
 {
        u64 pa; /* physical address */
@@ -615,7 +613,7 @@ static void
 sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
 {
        u32 iovp = (u32) SBA_IOVP(ioc,iova);
-       u64 *pdir_ptr = &ioc->pdir_base[PDIR_INDEX(iovp)];
+       __le64 *pdir_ptr = &ioc->pdir_base[PDIR_INDEX(iovp)];
 
 #ifdef ASSERT_PDIR_SANITY
        /* Assert first pdir entry is set.
@@ -716,7 +714,7 @@ sba_map_single(struct device *dev, void *addr, size_t size,
        unsigned long flags; 
        dma_addr_t iovp;
        dma_addr_t offset;
-       u64 *pdir_start;
+       __le64 *pdir_start;
        int pide;
 
        ioc = GET_IOC(dev);
@@ -1434,7 +1432,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
 
        ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64);
 
-       DBG_INIT("%s() hpa 0x%lx mem %ldMB IOV %dMB (%d bits)\n",
+       DBG_INIT("%s() hpa %px mem %ldMB IOV %dMB (%d bits)\n",
                        __func__,
                        ioc->ioc_hpa,
                        (unsigned long) totalram_pages() >> (20 - PAGE_SHIFT),
@@ -1471,7 +1469,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
        ioc->iovp_mask = ~(iova_space_mask + PAGE_SIZE - 1);
 #endif
 
-       DBG_INIT("%s() IOV base 0x%lx mask 0x%0lx\n",
+       DBG_INIT("%s() IOV base %#lx mask %#0lx\n",
                __func__, ioc->ibase, ioc->imask);
 
        /*
@@ -1583,7 +1581,7 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
 
        if (!IS_PLUTO(sba_dev->dev)) {
                ioc_ctl = READ_REG(sba_dev->sba_hpa+IOC_CTRL);
-               DBG_INIT("%s() hpa 0x%lx ioc_ctl 0x%Lx ->",
+               DBG_INIT("%s() hpa %px ioc_ctl 0x%Lx ->",
                        __func__, sba_dev->sba_hpa, ioc_ctl);
                ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC | IOC_CTRL_CE);
                ioc_ctl |= IOC_CTRL_DD | IOC_CTRL_D4 | IOC_CTRL_TC;
@@ -1668,14 +1666,14 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
                /* flush out the last writes */
                READ_REG(sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
 
-               DBG_INIT("      ioc[%d] ROPE_CFG 0x%Lx  ROPE_DBG 0x%Lx\n",
+               DBG_INIT("      ioc[%d] ROPE_CFG %#lx  ROPE_DBG %lx\n",
                                i,
-                               READ_REG(sba_dev->ioc[i].ioc_hpa + 0x40),
-                               READ_REG(sba_dev->ioc[i].ioc_hpa + 0x50)
+                               (unsigned long) READ_REG(sba_dev->ioc[i].ioc_hpa + 0x40),
+                               (unsigned long) READ_REG(sba_dev->ioc[i].ioc_hpa + 0x50)
                        );
-               DBG_INIT("      STATUS_CONTROL 0x%Lx  FLUSH_CTRL 0x%Lx\n",
-                               READ_REG(sba_dev->ioc[i].ioc_hpa + 0x108),
-                               READ_REG(sba_dev->ioc[i].ioc_hpa + 0x400)
+               DBG_INIT("      STATUS_CONTROL %#lx  FLUSH_CTRL %#lx\n",
+                               (unsigned long) READ_REG(sba_dev->ioc[i].ioc_hpa + 0x108),
+                               (unsigned long) READ_REG(sba_dev->ioc[i].ioc_hpa + 0x400)
                        );
 
                if (IS_PLUTO(sba_dev->dev)) {
@@ -1739,7 +1737,7 @@ sba_common_init(struct sba_device *sba_dev)
 #ifdef ASSERT_PDIR_SANITY
                /* Mark first bit busy - ie no IOVA 0 */
                sba_dev->ioc[i].res_map[0] = 0x80;
-               sba_dev->ioc[i].pdir_base[0] = 0xeeffc0addbba0080ULL;
+               sba_dev->ioc[i].pdir_base[0] = (__force __le64) 0xeeffc0addbba0080ULL;
 #endif
 
                /* Third (and last) part of PIRANHA BUG */
@@ -1899,9 +1897,7 @@ static int __init sba_driver_callback(struct parisc_device *dev)
        int i;
        char *version;
        void __iomem *sba_addr = ioremap(dev->hpa.start, SBA_FUNC_SIZE);
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *root;
-#endif
+       struct proc_dir_entry *root __maybe_unused;
 
        sba_dump_ranges(sba_addr);
 
@@ -1967,7 +1963,6 @@ static int __init sba_driver_callback(struct parisc_device *dev)
 
        hppa_dma_ops = &sba_ops;
 
-#ifdef CONFIG_PROC_FS
        switch (dev->id.hversion) {
        case PLUTO_MCKINLEY_PORT:
                if (!proc_mckinley_root)
@@ -1985,7 +1980,6 @@ static int __init sba_driver_callback(struct parisc_device *dev)
 
        proc_create_single("sba_iommu", 0, root, sba_proc_info);
        proc_create_single("sba_iommu-bitmap", 0, root, sba_proc_bitmap_info);
-#endif
        return 0;
 }
 
index e85ff946e8c8cc338442f7dd4b4b8b52c1e44e69..9c8fd69ae5ad8ea2ed8cbe2c20c7f67216b0978f 100644 (file)
@@ -229,6 +229,7 @@ int pcie_aer_is_native(struct pci_dev *dev)
 
        return pcie_ports_native || host->native_aer;
 }
+EXPORT_SYMBOL_NS_GPL(pcie_aer_is_native, CXL);
 
 static int pci_enable_pcie_error_reporting(struct pci_dev *dev)
 {
index 58a2b1a1cae4c03c60416cf72f909c33fecf6d90..1f3803bde7ee16067d4aa801057076268dfe4b51 100644 (file)
@@ -29,10 +29,8 @@ extern bool pcie_ports_dpc_native;
 
 #ifdef CONFIG_PCIEAER
 int pcie_aer_init(void);
-int pcie_aer_is_native(struct pci_dev *dev);
 #else
 static inline int pcie_aer_init(void) { return 0; }
-static inline int pcie_aer_is_native(struct pci_dev *dev) { return 0; }
 #endif
 
 #ifdef CONFIG_HOTPLUG_PCI_PCIE
index 382793e73a60a8b3f4ade16b00768fc368eb50e2..f7dfa0e785fd6e0cc603b2a9a12b848e967a0c1d 100644 (file)
@@ -60,6 +60,7 @@ config MLXBF_BOOTCTL
        tristate "Mellanox BlueField Firmware Boot Control driver"
        depends on ARM64
        depends on ACPI
+       depends on NET
        help
          The Mellanox BlueField firmware implements functionality to
          request swapping the primary and alternate eMMC boot partition,
@@ -80,8 +81,8 @@ config MLXBF_PMC
 
 config NVSW_SN2201
        tristate "Nvidia SN2201 platform driver support"
-       depends on HWMON
-       depends on I2C
+       depends on HWMON && I2C
+       depends on ACPI || COMPILE_TEST
        select REGMAP_I2C
        help
          This driver provides support for the Nvidia SN2201 platform.
index be967d797c28e04c6ce726b434e0edb322737f88..2d4bbe99959ef45e614707ada7875e3eec8e6c5e 100644 (file)
@@ -191,6 +191,7 @@ static const struct mlxbf_pmc_events mlxbf_pmc_smgen_events[] = {
 };
 
 static const struct mlxbf_pmc_events mlxbf_pmc_trio_events_1[] = {
+       { 0x0, "DISABLE" },
        { 0xa0, "TPIO_DATA_BEAT" },
        { 0xa1, "TDMA_DATA_BEAT" },
        { 0xa2, "MAP_DATA_BEAT" },
@@ -214,6 +215,7 @@ static const struct mlxbf_pmc_events mlxbf_pmc_trio_events_1[] = {
 };
 
 static const struct mlxbf_pmc_events mlxbf_pmc_trio_events_2[] = {
+       { 0x0, "DISABLE" },
        { 0xa0, "TPIO_DATA_BEAT" },
        { 0xa1, "TDMA_DATA_BEAT" },
        { 0xa2, "MAP_DATA_BEAT" },
@@ -246,6 +248,7 @@ static const struct mlxbf_pmc_events mlxbf_pmc_trio_events_2[] = {
 };
 
 static const struct mlxbf_pmc_events mlxbf_pmc_ecc_events[] = {
+       { 0x0, "DISABLE" },
        { 0x100, "ECC_SINGLE_ERROR_CNT" },
        { 0x104, "ECC_DOUBLE_ERROR_CNT" },
        { 0x114, "SERR_INJ" },
@@ -258,6 +261,7 @@ static const struct mlxbf_pmc_events mlxbf_pmc_ecc_events[] = {
 };
 
 static const struct mlxbf_pmc_events mlxbf_pmc_mss_events[] = {
+       { 0x0, "DISABLE" },
        { 0xc0, "RXREQ_MSS" },
        { 0xc1, "RXDAT_MSS" },
        { 0xc2, "TXRSP_MSS" },
@@ -265,6 +269,7 @@ static const struct mlxbf_pmc_events mlxbf_pmc_mss_events[] = {
 };
 
 static const struct mlxbf_pmc_events mlxbf_pmc_hnf_events[] = {
+       { 0x0, "DISABLE" },
        { 0x45, "HNF_REQUESTS" },
        { 0x46, "HNF_REJECTS" },
        { 0x47, "ALL_BUSY" },
@@ -323,6 +328,7 @@ static const struct mlxbf_pmc_events mlxbf_pmc_hnf_events[] = {
 };
 
 static const struct mlxbf_pmc_events mlxbf_pmc_hnfnet_events[] = {
+       { 0x0, "DISABLE" },
        { 0x12, "CDN_REQ" },
        { 0x13, "DDN_REQ" },
        { 0x14, "NDN_REQ" },
@@ -892,7 +898,7 @@ static int mlxbf_pmc_read_event(int blk_num, uint32_t cnt_num, bool is_l3,
                                uint64_t *result)
 {
        uint32_t perfcfg_offset, perfval_offset;
-       uint64_t perfmon_cfg, perfevt, perfctl;
+       uint64_t perfmon_cfg, perfevt;
 
        if (cnt_num >= pmc->block[blk_num].counters)
                return -EINVAL;
@@ -904,25 +910,6 @@ static int mlxbf_pmc_read_event(int blk_num, uint32_t cnt_num, bool is_l3,
        perfval_offset = perfcfg_offset +
                         pmc->block[blk_num].counters * MLXBF_PMC_REG_SIZE;
 
-       /* Set counter in "read" mode */
-       perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR,
-                                MLXBF_PMC_PERFCTL);
-       perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_STROBE, 1);
-       perfmon_cfg |= FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_WR_R_B, 0);
-
-       if (mlxbf_pmc_write(pmc->block[blk_num].mmio_base + perfcfg_offset,
-                           MLXBF_PMC_WRITE_REG_64, perfmon_cfg))
-               return -EFAULT;
-
-       /* Check if the counter is enabled */
-
-       if (mlxbf_pmc_read(pmc->block[blk_num].mmio_base + perfval_offset,
-                          MLXBF_PMC_READ_REG_64, &perfctl))
-               return -EFAULT;
-
-       if (!FIELD_GET(MLXBF_PMC_PERFCTL_EN0, perfctl))
-               return -EINVAL;
-
        /* Set counter in "read" mode */
        perfmon_cfg = FIELD_PREP(MLXBF_PMC_PERFMON_CONFIG_ADDR,
                                 MLXBF_PMC_PERFEVT);
@@ -1008,7 +995,7 @@ static ssize_t mlxbf_pmc_counter_show(struct device *dev,
        } else
                return -EINVAL;
 
-       return sprintf(buf, "0x%llx\n", value);
+       return sysfs_emit(buf, "0x%llx\n", value);
 }
 
 /* Store function for "counter" sysfs files */
@@ -1078,13 +1065,13 @@ static ssize_t mlxbf_pmc_event_show(struct device *dev,
 
        err = mlxbf_pmc_read_event(blk_num, cnt_num, is_l3, &evt_num);
        if (err)
-               return sprintf(buf, "No event being monitored\n");
+               return sysfs_emit(buf, "No event being monitored\n");
 
        evt_name = mlxbf_pmc_get_event_name(pmc->block_name[blk_num], evt_num);
        if (!evt_name)
                return -EINVAL;
 
-       return sprintf(buf, "0x%llx: %s\n", evt_num, evt_name);
+       return sysfs_emit(buf, "0x%llx: %s\n", evt_num, evt_name);
 }
 
 /* Store function for "event" sysfs files */
@@ -1139,9 +1126,9 @@ static ssize_t mlxbf_pmc_event_list_show(struct device *dev,
                return -EINVAL;
 
        for (i = 0, buf[0] = '\0'; i < size; ++i) {
-               len += sprintf(e_info, "0x%x: %s\n", events[i].evt_num,
-                              events[i].evt_name);
-               if (len > PAGE_SIZE)
+               len += snprintf(e_info, sizeof(e_info), "0x%x: %s\n",
+                               events[i].evt_num, events[i].evt_name);
+               if (len >= PAGE_SIZE)
                        break;
                strcat(buf, e_info);
                ret = len;
@@ -1168,7 +1155,7 @@ static ssize_t mlxbf_pmc_enable_show(struct device *dev,
 
        value = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_CFG_EN, perfcnt_cfg);
 
-       return sprintf(buf, "%d\n", value);
+       return sysfs_emit(buf, "%d\n", value);
 }
 
 /* Store function for "enable" sysfs files - only for l3cache */
index b600b77d91ef2c3834d6e837b1f64f78f962ba97..f3696a54a2bd72326556a7d6e60f6d76ce36eaa1 100644 (file)
@@ -59,6 +59,7 @@ struct mlxbf_tmfifo;
  * @vq: pointer to the virtio virtqueue
  * @desc: current descriptor of the pending packet
  * @desc_head: head descriptor of the pending packet
+ * @drop_desc: dummy desc for packet dropping
  * @cur_len: processed length of the current descriptor
  * @rem_len: remaining length of the pending packet
  * @pkt_len: total length of the pending packet
@@ -75,6 +76,7 @@ struct mlxbf_tmfifo_vring {
        struct virtqueue *vq;
        struct vring_desc *desc;
        struct vring_desc *desc_head;
+       struct vring_desc drop_desc;
        int cur_len;
        int rem_len;
        u32 pkt_len;
@@ -86,6 +88,14 @@ struct mlxbf_tmfifo_vring {
        struct mlxbf_tmfifo *fifo;
 };
 
+/* Check whether vring is in drop mode. */
+#define IS_VRING_DROP(_r) ({ \
+       typeof(_r) (r) = (_r); \
+       (r->desc_head == &r->drop_desc ? true : false); })
+
+/* A stub length to drop maximum length packet. */
+#define VRING_DROP_DESC_MAX_LEN                GENMASK(15, 0)
+
 /* Interrupt types. */
 enum {
        MLXBF_TM_RX_LWM_IRQ,
@@ -214,7 +224,7 @@ static u8 mlxbf_tmfifo_net_default_mac[ETH_ALEN] = {
 static efi_char16_t mlxbf_tmfifo_efi_name[] = L"RshimMacAddr";
 
 /* Maximum L2 header length. */
-#define MLXBF_TMFIFO_NET_L2_OVERHEAD   36
+#define MLXBF_TMFIFO_NET_L2_OVERHEAD   (ETH_HLEN + VLAN_HLEN)
 
 /* Supported virtio-net features. */
 #define MLXBF_TMFIFO_NET_FEATURES \
@@ -262,6 +272,7 @@ static int mlxbf_tmfifo_alloc_vrings(struct mlxbf_tmfifo *fifo,
                vring->align = SMP_CACHE_BYTES;
                vring->index = i;
                vring->vdev_id = tm_vdev->vdev.id.device;
+               vring->drop_desc.len = VRING_DROP_DESC_MAX_LEN;
                dev = &tm_vdev->vdev.dev;
 
                size = vring_size(vring->num, vring->align);
@@ -367,7 +378,7 @@ static u32 mlxbf_tmfifo_get_pkt_len(struct mlxbf_tmfifo_vring *vring,
        return len;
 }
 
-static void mlxbf_tmfifo_release_pending_pkt(struct mlxbf_tmfifo_vring *vring)
+static void mlxbf_tmfifo_release_pkt(struct mlxbf_tmfifo_vring *vring)
 {
        struct vring_desc *desc_head;
        u32 len = 0;
@@ -596,19 +607,25 @@ static void mlxbf_tmfifo_rxtx_word(struct mlxbf_tmfifo_vring *vring,
 
        if (vring->cur_len + sizeof(u64) <= len) {
                /* The whole word. */
-               if (is_rx)
-                       memcpy(addr + vring->cur_len, &data, sizeof(u64));
-               else
-                       memcpy(&data, addr + vring->cur_len, sizeof(u64));
+               if (!IS_VRING_DROP(vring)) {
+                       if (is_rx)
+                               memcpy(addr + vring->cur_len, &data,
+                                      sizeof(u64));
+                       else
+                               memcpy(&data, addr + vring->cur_len,
+                                      sizeof(u64));
+               }
                vring->cur_len += sizeof(u64);
        } else {
                /* Leftover bytes. */
-               if (is_rx)
-                       memcpy(addr + vring->cur_len, &data,
-                              len - vring->cur_len);
-               else
-                       memcpy(&data, addr + vring->cur_len,
-                              len - vring->cur_len);
+               if (!IS_VRING_DROP(vring)) {
+                       if (is_rx)
+                               memcpy(addr + vring->cur_len, &data,
+                                      len - vring->cur_len);
+                       else
+                               memcpy(&data, addr + vring->cur_len,
+                                      len - vring->cur_len);
+               }
                vring->cur_len = len;
        }
 
@@ -625,13 +642,14 @@ static void mlxbf_tmfifo_rxtx_word(struct mlxbf_tmfifo_vring *vring,
  * flag is set.
  */
 static void mlxbf_tmfifo_rxtx_header(struct mlxbf_tmfifo_vring *vring,
-                                    struct vring_desc *desc,
+                                    struct vring_desc **desc,
                                     bool is_rx, bool *vring_change)
 {
        struct mlxbf_tmfifo *fifo = vring->fifo;
        struct virtio_net_config *config;
        struct mlxbf_tmfifo_msg_hdr hdr;
        int vdev_id, hdr_len;
+       bool drop_rx = false;
 
        /* Read/Write packet header. */
        if (is_rx) {
@@ -651,8 +669,8 @@ static void mlxbf_tmfifo_rxtx_header(struct mlxbf_tmfifo_vring *vring,
                        if (ntohs(hdr.len) >
                            __virtio16_to_cpu(virtio_legacy_is_little_endian(),
                                              config->mtu) +
-                           MLXBF_TMFIFO_NET_L2_OVERHEAD)
-                               return;
+                                             MLXBF_TMFIFO_NET_L2_OVERHEAD)
+                               drop_rx = true;
                } else {
                        vdev_id = VIRTIO_ID_CONSOLE;
                        hdr_len = 0;
@@ -667,16 +685,25 @@ static void mlxbf_tmfifo_rxtx_header(struct mlxbf_tmfifo_vring *vring,
 
                        if (!tm_dev2)
                                return;
-                       vring->desc = desc;
+                       vring->desc = *desc;
                        vring = &tm_dev2->vrings[MLXBF_TMFIFO_VRING_RX];
                        *vring_change = true;
                }
+
+               if (drop_rx && !IS_VRING_DROP(vring)) {
+                       if (vring->desc_head)
+                               mlxbf_tmfifo_release_pkt(vring);
+                       *desc = &vring->drop_desc;
+                       vring->desc_head = *desc;
+                       vring->desc = *desc;
+               }
+
                vring->pkt_len = ntohs(hdr.len) + hdr_len;
        } else {
                /* Network virtio has an extra header. */
                hdr_len = (vring->vdev_id == VIRTIO_ID_NET) ?
                           sizeof(struct virtio_net_hdr) : 0;
-               vring->pkt_len = mlxbf_tmfifo_get_pkt_len(vring, desc);
+               vring->pkt_len = mlxbf_tmfifo_get_pkt_len(vring, *desc);
                hdr.type = (vring->vdev_id == VIRTIO_ID_NET) ?
                            VIRTIO_ID_NET : VIRTIO_ID_CONSOLE;
                hdr.len = htons(vring->pkt_len - hdr_len);
@@ -709,15 +736,23 @@ static bool mlxbf_tmfifo_rxtx_one_desc(struct mlxbf_tmfifo_vring *vring,
        /* Get the descriptor of the next packet. */
        if (!vring->desc) {
                desc = mlxbf_tmfifo_get_next_pkt(vring, is_rx);
-               if (!desc)
-                       return false;
+               if (!desc) {
+                       /* Drop next Rx packet to avoid stuck. */
+                       if (is_rx) {
+                               desc = &vring->drop_desc;
+                               vring->desc_head = desc;
+                               vring->desc = desc;
+                       } else {
+                               return false;
+                       }
+               }
        } else {
                desc = vring->desc;
        }
 
        /* Beginning of a packet. Start to Rx/Tx packet header. */
        if (vring->pkt_len == 0) {
-               mlxbf_tmfifo_rxtx_header(vring, desc, is_rx, &vring_change);
+               mlxbf_tmfifo_rxtx_header(vring, &desc, is_rx, &vring_change);
                (*avail)--;
 
                /* Return if new packet is for another ring. */
@@ -743,17 +778,24 @@ static bool mlxbf_tmfifo_rxtx_one_desc(struct mlxbf_tmfifo_vring *vring,
                vring->rem_len -= len;
 
                /* Get the next desc on the chain. */
-               if (vring->rem_len > 0 &&
+               if (!IS_VRING_DROP(vring) && vring->rem_len > 0 &&
                    (virtio16_to_cpu(vdev, desc->flags) & VRING_DESC_F_NEXT)) {
                        idx = virtio16_to_cpu(vdev, desc->next);
                        desc = &vr->desc[idx];
                        goto mlxbf_tmfifo_desc_done;
                }
 
-               /* Done and release the pending packet. */
-               mlxbf_tmfifo_release_pending_pkt(vring);
+               /* Done and release the packet. */
                desc = NULL;
                fifo->vring[is_rx] = NULL;
+               if (!IS_VRING_DROP(vring)) {
+                       mlxbf_tmfifo_release_pkt(vring);
+               } else {
+                       vring->pkt_len = 0;
+                       vring->desc_head = NULL;
+                       vring->desc = NULL;
+                       return false;
+               }
 
                /*
                 * Make sure the load/store are in order before
@@ -933,7 +975,7 @@ static void mlxbf_tmfifo_virtio_del_vqs(struct virtio_device *vdev)
 
                /* Release the pending packet. */
                if (vring->desc)
-                       mlxbf_tmfifo_release_pending_pkt(vring);
+                       mlxbf_tmfifo_release_pkt(vring);
                vq = vring->vq;
                if (vq) {
                        vring->vq = NULL;
index fdf7da06af3067495fe7132e725a52542010ff8d..d85d895fee89431a42d94bfdde087f8e64183547 100644 (file)
@@ -478,6 +478,15 @@ static const struct dmi_system_id asus_quirks[] = {
                },
                .driver_data = &quirk_asus_tablet_mode,
        },
+       {
+               .callback = dmi_matched,
+               .ident = "ASUS ROG FLOW X16",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "GV601V"),
+               },
+               .driver_data = &quirk_asus_tablet_mode,
+       },
        {
                .callback = dmi_matched,
                .ident = "ASUS VivoBook E410MA",
index 6851d10d6582525509c2a3f05163abfbeb7a3802..a68df41334035185d5301006e4f70f1f3f29af49 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 
@@ -231,19 +232,15 @@ static inline u32 ipc_data_readl(struct intel_scu_ipc_dev *scu, u32 offset)
 /* Wait till scu status is busy */
 static inline int busy_loop(struct intel_scu_ipc_dev *scu)
 {
-       unsigned long end = jiffies + IPC_TIMEOUT;
-
-       do {
-               u32 status;
-
-               status = ipc_read_status(scu);
-               if (!(status & IPC_STATUS_BUSY))
-                       return (status & IPC_STATUS_ERR) ? -EIO : 0;
+       u8 status;
+       int err;
 
-               usleep_range(50, 100);
-       } while (time_before(jiffies, end));
+       err = readx_poll_timeout(ipc_read_status, scu, status, !(status & IPC_STATUS_BUSY),
+                                100, jiffies_to_usecs(IPC_TIMEOUT));
+       if (err)
+               return err;
 
-       return -ETIMEDOUT;
+       return (status & IPC_STATUS_ERR) ? -EIO : 0;
 }
 
 /* Wait till ipc ioc interrupt is received or timeout in 10 HZ */
@@ -251,10 +248,12 @@ static inline int ipc_wait_for_interrupt(struct intel_scu_ipc_dev *scu)
 {
        int status;
 
-       if (!wait_for_completion_timeout(&scu->cmd_complete, IPC_TIMEOUT))
-               return -ETIMEDOUT;
+       wait_for_completion_timeout(&scu->cmd_complete, IPC_TIMEOUT);
 
        status = ipc_read_status(scu);
+       if (status & IPC_STATUS_BUSY)
+               return -ETIMEDOUT;
+
        if (status & IPC_STATUS_ERR)
                return -EIO;
 
@@ -266,6 +265,24 @@ static int intel_scu_ipc_check_status(struct intel_scu_ipc_dev *scu)
        return scu->irq > 0 ? ipc_wait_for_interrupt(scu) : busy_loop(scu);
 }
 
+static struct intel_scu_ipc_dev *intel_scu_ipc_get(struct intel_scu_ipc_dev *scu)
+{
+       u8 status;
+
+       if (!scu)
+               scu = ipcdev;
+       if (!scu)
+               return ERR_PTR(-ENODEV);
+
+       status = ipc_read_status(scu);
+       if (status & IPC_STATUS_BUSY) {
+               dev_dbg(&scu->dev, "device is busy\n");
+               return ERR_PTR(-EBUSY);
+       }
+
+       return scu;
+}
+
 /* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */
 static int pwr_reg_rdwr(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data,
                        u32 count, u32 op, u32 id)
@@ -279,11 +296,10 @@ static int pwr_reg_rdwr(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data,
        memset(cbuf, 0, sizeof(cbuf));
 
        mutex_lock(&ipclock);
-       if (!scu)
-               scu = ipcdev;
-       if (!scu) {
+       scu = intel_scu_ipc_get(scu);
+       if (IS_ERR(scu)) {
                mutex_unlock(&ipclock);
-               return -ENODEV;
+               return PTR_ERR(scu);
        }
 
        for (nc = 0; nc < count; nc++, offset += 2) {
@@ -438,13 +454,12 @@ int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd,
        int err;
 
        mutex_lock(&ipclock);
-       if (!scu)
-               scu = ipcdev;
-       if (!scu) {
+       scu = intel_scu_ipc_get(scu);
+       if (IS_ERR(scu)) {
                mutex_unlock(&ipclock);
-               return -ENODEV;
+               return PTR_ERR(scu);
        }
-       scu = ipcdev;
+
        cmdval = sub << 12 | cmd;
        ipc_command(scu, cmdval);
        err = intel_scu_ipc_check_status(scu);
@@ -484,11 +499,10 @@ int intel_scu_ipc_dev_command_with_size(struct intel_scu_ipc_dev *scu, int cmd,
                return -EINVAL;
 
        mutex_lock(&ipclock);
-       if (!scu)
-               scu = ipcdev;
-       if (!scu) {
+       scu = intel_scu_ipc_get(scu);
+       if (IS_ERR(scu)) {
                mutex_unlock(&ipclock);
-               return -ENODEV;
+               return PTR_ERR(scu);
        }
 
        memcpy(inbuf, in, inlen);
index d70c89d3253440b725bf32791a8f0d1a49f408d6..41584427dc323b7aafb7f214d9a35abc9b272d8d 100644 (file)
@@ -4116,9 +4116,11 @@ static void hotkey_resume(void)
 {
        tpacpi_disable_brightness_delay();
 
+       mutex_lock(&hotkey_mutex);
        if (hotkey_status_set(true) < 0 ||
            hotkey_mask_set(hotkey_acpi_mask) < 0)
                pr_err("error while attempting to reset the event firmware interface\n");
+       mutex_unlock(&hotkey_mutex);
 
        tpacpi_send_radiosw_update();
        tpacpi_input_send_tabletsw();
diff --git a/drivers/pmdomain/Makefile b/drivers/pmdomain/Makefile
new file mode 100644 (file)
index 0000000..6667536
--- /dev/null
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-y                                  += actions/
+obj-y                                  += amlogic/
+obj-y                                  += apple/
+obj-y                                  += bcm/
+obj-y                                  += imx/
+obj-y                                  += mediatek/
+obj-y                                  += qcom/
+obj-y                                  += renesas/
+obj-y                                  += rockchip/
+obj-y                                  += samsung/
+obj-y                                  += st/
+obj-y                                  += starfive/
+obj-y                                  += sunxi/
+obj-y                                  += tegra/
+obj-y                                  += ti/
+obj-y                                  += xilinx/
diff --git a/drivers/pmdomain/actions/Makefile b/drivers/pmdomain/actions/Makefile
new file mode 100644 (file)
index 0000000..7e8aa47
--- /dev/null
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+obj-$(CONFIG_OWL_PM_DOMAINS_HELPER)    += owl-sps-helper.o
+obj-$(CONFIG_OWL_PM_DOMAINS)           += owl-sps.o
diff --git a/drivers/pmdomain/actions/owl-sps-helper.c b/drivers/pmdomain/actions/owl-sps-helper.c
new file mode 100644 (file)
index 0000000..e3f3660
--- /dev/null
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Actions Semi Owl Smart Power System (SPS) shared helpers
+ *
+ * Copyright 2012 Actions Semi Inc.
+ * Author: Actions Semi, Inc.
+ *
+ * Copyright (c) 2017 Andreas Färber
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/soc/actions/owl-sps.h>
+
+#define OWL_SPS_PG_CTL 0x0
+
+int owl_sps_set_pg(void __iomem *base, u32 pwr_mask, u32 ack_mask, bool enable)
+{
+       u32 val;
+       bool ack;
+       int timeout;
+
+       val = readl(base + OWL_SPS_PG_CTL);
+       ack = val & ack_mask;
+       if (ack == enable)
+               return 0;
+
+       if (enable)
+               val |= pwr_mask;
+       else
+               val &= ~pwr_mask;
+
+       writel(val, base + OWL_SPS_PG_CTL);
+
+       for (timeout = 5000; timeout > 0; timeout -= 50) {
+               val = readl(base + OWL_SPS_PG_CTL);
+               if ((val & ack_mask) == (enable ? ack_mask : 0))
+                       break;
+               udelay(50);
+       }
+       if (timeout <= 0)
+               return -ETIMEDOUT;
+
+       udelay(10);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(owl_sps_set_pg);
diff --git a/drivers/pmdomain/actions/owl-sps.c b/drivers/pmdomain/actions/owl-sps.c
new file mode 100644 (file)
index 0000000..73a9e0b
--- /dev/null
@@ -0,0 +1,320 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Actions Semi Owl Smart Power System (SPS)
+ *
+ * Copyright 2012 Actions Semi Inc.
+ * Author: Actions Semi, Inc.
+ *
+ * Copyright (c) 2017 Andreas Färber
+ */
+
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pm_domain.h>
+#include <linux/soc/actions/owl-sps.h>
+#include <dt-bindings/power/owl-s500-powergate.h>
+#include <dt-bindings/power/owl-s700-powergate.h>
+#include <dt-bindings/power/owl-s900-powergate.h>
+
+struct owl_sps_domain_info {
+       const char *name;
+       int pwr_bit;
+       int ack_bit;
+       unsigned int genpd_flags;
+};
+
+struct owl_sps_info {
+       unsigned num_domains;
+       const struct owl_sps_domain_info *domains;
+};
+
+struct owl_sps {
+       struct device *dev;
+       const struct owl_sps_info *info;
+       void __iomem *base;
+       struct genpd_onecell_data genpd_data;
+       struct generic_pm_domain *domains[];
+};
+
+#define to_owl_pd(gpd) container_of(gpd, struct owl_sps_domain, genpd)
+
+struct owl_sps_domain {
+       struct generic_pm_domain genpd;
+       const struct owl_sps_domain_info *info;
+       struct owl_sps *sps;
+};
+
+static int owl_sps_set_power(struct owl_sps_domain *pd, bool enable)
+{
+       u32 pwr_mask, ack_mask;
+
+       ack_mask = BIT(pd->info->ack_bit);
+       pwr_mask = BIT(pd->info->pwr_bit);
+
+       return owl_sps_set_pg(pd->sps->base, pwr_mask, ack_mask, enable);
+}
+
+static int owl_sps_power_on(struct generic_pm_domain *domain)
+{
+       struct owl_sps_domain *pd = to_owl_pd(domain);
+
+       dev_dbg(pd->sps->dev, "%s power on", pd->info->name);
+
+       return owl_sps_set_power(pd, true);
+}
+
+static int owl_sps_power_off(struct generic_pm_domain *domain)
+{
+       struct owl_sps_domain *pd = to_owl_pd(domain);
+
+       dev_dbg(pd->sps->dev, "%s power off", pd->info->name);
+
+       return owl_sps_set_power(pd, false);
+}
+
+static int owl_sps_init_domain(struct owl_sps *sps, int index)
+{
+       struct owl_sps_domain *pd;
+
+       pd = devm_kzalloc(sps->dev, sizeof(*pd), GFP_KERNEL);
+       if (!pd)
+               return -ENOMEM;
+
+       pd->info = &sps->info->domains[index];
+       pd->sps = sps;
+
+       pd->genpd.name = pd->info->name;
+       pd->genpd.power_on = owl_sps_power_on;
+       pd->genpd.power_off = owl_sps_power_off;
+       pd->genpd.flags = pd->info->genpd_flags;
+       pm_genpd_init(&pd->genpd, NULL, false);
+
+       sps->genpd_data.domains[index] = &pd->genpd;
+
+       return 0;
+}
+
+static int owl_sps_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *match;
+       const struct owl_sps_info *sps_info;
+       struct owl_sps *sps;
+       int i, ret;
+
+       if (!pdev->dev.of_node) {
+               dev_err(&pdev->dev, "no device node\n");
+               return -ENODEV;
+       }
+
+       match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
+       if (!match || !match->data) {
+               dev_err(&pdev->dev, "unknown compatible or missing data\n");
+               return -EINVAL;
+       }
+
+       sps_info = match->data;
+
+       sps = devm_kzalloc(&pdev->dev,
+                          struct_size(sps, domains, sps_info->num_domains),
+                          GFP_KERNEL);
+       if (!sps)
+               return -ENOMEM;
+
+       sps->base = of_io_request_and_map(pdev->dev.of_node, 0, "owl-sps");
+       if (IS_ERR(sps->base)) {
+               dev_err(&pdev->dev, "failed to map sps registers\n");
+               return PTR_ERR(sps->base);
+       }
+
+       sps->dev = &pdev->dev;
+       sps->info = sps_info;
+       sps->genpd_data.domains = sps->domains;
+       sps->genpd_data.num_domains = sps_info->num_domains;
+
+       for (i = 0; i < sps_info->num_domains; i++) {
+               ret = owl_sps_init_domain(sps, i);
+               if (ret)
+                       return ret;
+       }
+
+       ret = of_genpd_add_provider_onecell(pdev->dev.of_node, &sps->genpd_data);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to add provider (%d)", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static const struct owl_sps_domain_info s500_sps_domains[] = {
+       [S500_PD_VDE] = {
+               .name = "VDE",
+               .pwr_bit = 0,
+               .ack_bit = 16,
+       },
+       [S500_PD_VCE_SI] = {
+               .name = "VCE_SI",
+               .pwr_bit = 1,
+               .ack_bit = 17,
+       },
+       [S500_PD_USB2_1] = {
+               .name = "USB2_1",
+               .pwr_bit = 2,
+               .ack_bit = 18,
+       },
+       [S500_PD_CPU2] = {
+               .name = "CPU2",
+               .pwr_bit = 5,
+               .ack_bit = 21,
+               .genpd_flags = GENPD_FLAG_ALWAYS_ON,
+       },
+       [S500_PD_CPU3] = {
+               .name = "CPU3",
+               .pwr_bit = 6,
+               .ack_bit = 22,
+               .genpd_flags = GENPD_FLAG_ALWAYS_ON,
+       },
+       [S500_PD_DMA] = {
+               .name = "DMA",
+               .pwr_bit = 8,
+               .ack_bit = 12,
+       },
+       [S500_PD_DS] = {
+               .name = "DS",
+               .pwr_bit = 9,
+               .ack_bit = 13,
+       },
+       [S500_PD_USB3] = {
+               .name = "USB3",
+               .pwr_bit = 10,
+               .ack_bit = 14,
+       },
+       [S500_PD_USB2_0] = {
+               .name = "USB2_0",
+               .pwr_bit = 11,
+               .ack_bit = 15,
+       },
+};
+
+static const struct owl_sps_info s500_sps_info = {
+       .num_domains = ARRAY_SIZE(s500_sps_domains),
+       .domains = s500_sps_domains,
+};
+
+static const struct owl_sps_domain_info s700_sps_domains[] = {
+       [S700_PD_VDE] = {
+               .name = "VDE",
+               .pwr_bit = 0,
+       },
+       [S700_PD_VCE_SI] = {
+               .name = "VCE_SI",
+               .pwr_bit = 1,
+       },
+       [S700_PD_USB2_1] = {
+               .name = "USB2_1",
+               .pwr_bit = 2,
+       },
+       [S700_PD_HDE] = {
+               .name = "HDE",
+               .pwr_bit = 7,
+       },
+       [S700_PD_DMA] = {
+               .name = "DMA",
+               .pwr_bit = 8,
+       },
+       [S700_PD_DS] = {
+               .name = "DS",
+               .pwr_bit = 9,
+       },
+       [S700_PD_USB3] = {
+               .name = "USB3",
+               .pwr_bit = 10,
+       },
+       [S700_PD_USB2_0] = {
+               .name = "USB2_0",
+               .pwr_bit = 11,
+       },
+};
+
+static const struct owl_sps_info s700_sps_info = {
+       .num_domains = ARRAY_SIZE(s700_sps_domains),
+       .domains = s700_sps_domains,
+};
+
+static const struct owl_sps_domain_info s900_sps_domains[] = {
+       [S900_PD_GPU_B] = {
+               .name = "GPU_B",
+               .pwr_bit = 3,
+       },
+       [S900_PD_VCE] = {
+               .name = "VCE",
+               .pwr_bit = 4,
+       },
+       [S900_PD_SENSOR] = {
+               .name = "SENSOR",
+               .pwr_bit = 5,
+       },
+       [S900_PD_VDE] = {
+               .name = "VDE",
+               .pwr_bit = 6,
+       },
+       [S900_PD_HDE] = {
+               .name = "HDE",
+               .pwr_bit = 7,
+       },
+       [S900_PD_USB3] = {
+               .name = "USB3",
+               .pwr_bit = 8,
+       },
+       [S900_PD_DDR0] = {
+               .name = "DDR0",
+               .pwr_bit = 9,
+       },
+       [S900_PD_DDR1] = {
+               .name = "DDR1",
+               .pwr_bit = 10,
+       },
+       [S900_PD_DE] = {
+               .name = "DE",
+               .pwr_bit = 13,
+       },
+       [S900_PD_NAND] = {
+               .name = "NAND",
+               .pwr_bit = 14,
+       },
+       [S900_PD_USB2_H0] = {
+               .name = "USB2_H0",
+               .pwr_bit = 15,
+       },
+       [S900_PD_USB2_H1] = {
+               .name = "USB2_H1",
+               .pwr_bit = 16,
+       },
+};
+
+static const struct owl_sps_info s900_sps_info = {
+       .num_domains = ARRAY_SIZE(s900_sps_domains),
+       .domains = s900_sps_domains,
+};
+
+static const struct of_device_id owl_sps_of_matches[] = {
+       { .compatible = "actions,s500-sps", .data = &s500_sps_info },
+       { .compatible = "actions,s700-sps", .data = &s700_sps_info },
+       { .compatible = "actions,s900-sps", .data = &s900_sps_info },
+       { }
+};
+
+static struct platform_driver owl_sps_platform_driver = {
+       .probe = owl_sps_probe,
+       .driver = {
+               .name = "owl-sps",
+               .of_match_table = owl_sps_of_matches,
+               .suppress_bind_attrs = true,
+       },
+};
+
+static int __init owl_sps_init(void)
+{
+       return platform_driver_register(&owl_sps_platform_driver);
+}
+postcore_initcall(owl_sps_init);
diff --git a/drivers/pmdomain/amlogic/Makefile b/drivers/pmdomain/amlogic/Makefile
new file mode 100644 (file)
index 0000000..3d58abd
--- /dev/null
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o
+obj-$(CONFIG_MESON_EE_PM_DOMAINS) += meson-ee-pwrc.o
+obj-$(CONFIG_MESON_SECURE_PM_DOMAINS) += meson-secure-pwrc.o
diff --git a/drivers/pmdomain/amlogic/meson-ee-pwrc.c b/drivers/pmdomain/amlogic/meson-ee-pwrc.c
new file mode 100644 (file)
index 0000000..cfb796d
--- /dev/null
@@ -0,0 +1,635 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/bitfield.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/reset-controller.h>
+#include <linux/reset.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <dt-bindings/power/meson8-power.h>
+#include <dt-bindings/power/meson-axg-power.h>
+#include <dt-bindings/power/meson-g12a-power.h>
+#include <dt-bindings/power/meson-gxbb-power.h>
+#include <dt-bindings/power/meson-sm1-power.h>
+
+/* AO Offsets */
+
+#define GX_AO_RTI_GEN_PWR_SLEEP0       (0x3a << 2)
+#define GX_AO_RTI_GEN_PWR_ISO0         (0x3b << 2)
+
+/*
+ * Meson8/Meson8b/Meson8m2 only expose the power management registers of the
+ * AO-bus as syscon. 0x3a from GX translates to 0x02, 0x3b translates to 0x03
+ * and so on.
+ */
+#define MESON8_AO_RTI_GEN_PWR_SLEEP0   (0x02 << 2)
+#define MESON8_AO_RTI_GEN_PWR_ISO0     (0x03 << 2)
+
+/* HHI Offsets */
+
+#define HHI_MEM_PD_REG0                        (0x40 << 2)
+#define HHI_VPU_MEM_PD_REG0            (0x41 << 2)
+#define HHI_VPU_MEM_PD_REG1            (0x42 << 2)
+#define HHI_VPU_MEM_PD_REG3            (0x43 << 2)
+#define HHI_VPU_MEM_PD_REG4            (0x44 << 2)
+#define HHI_AUDIO_MEM_PD_REG0          (0x45 << 2)
+#define HHI_NANOQ_MEM_PD_REG0          (0x46 << 2)
+#define HHI_NANOQ_MEM_PD_REG1          (0x47 << 2)
+#define HHI_VPU_MEM_PD_REG2            (0x4d << 2)
+
+#define G12A_HHI_NANOQ_MEM_PD_REG0     (0x43 << 2)
+#define G12A_HHI_NANOQ_MEM_PD_REG1     (0x44 << 2)
+
+struct meson_ee_pwrc;
+struct meson_ee_pwrc_domain;
+
+struct meson_ee_pwrc_mem_domain {
+       unsigned int reg;
+       unsigned int mask;
+};
+
+struct meson_ee_pwrc_top_domain {
+       unsigned int sleep_reg;
+       unsigned int sleep_mask;
+       unsigned int iso_reg;
+       unsigned int iso_mask;
+};
+
+struct meson_ee_pwrc_domain_desc {
+       char *name;
+       unsigned int reset_names_count;
+       unsigned int clk_names_count;
+       struct meson_ee_pwrc_top_domain *top_pd;
+       unsigned int mem_pd_count;
+       struct meson_ee_pwrc_mem_domain *mem_pd;
+       bool (*is_powered_off)(struct meson_ee_pwrc_domain *pwrc_domain);
+};
+
+struct meson_ee_pwrc_domain_data {
+       unsigned int count;
+       struct meson_ee_pwrc_domain_desc *domains;
+};
+
+/* TOP Power Domains */
+
+static struct meson_ee_pwrc_top_domain gx_pwrc_vpu = {
+       .sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0,
+       .sleep_mask = BIT(8),
+       .iso_reg = GX_AO_RTI_GEN_PWR_SLEEP0,
+       .iso_mask = BIT(9),
+};
+
+static struct meson_ee_pwrc_top_domain meson8_pwrc_vpu = {
+       .sleep_reg = MESON8_AO_RTI_GEN_PWR_SLEEP0,
+       .sleep_mask = BIT(8),
+       .iso_reg = MESON8_AO_RTI_GEN_PWR_SLEEP0,
+       .iso_mask = BIT(9),
+};
+
+#define SM1_EE_PD(__bit)                                       \
+       {                                                       \
+               .sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0,          \
+               .sleep_mask = BIT(__bit),                       \
+               .iso_reg = GX_AO_RTI_GEN_PWR_ISO0,              \
+               .iso_mask = BIT(__bit),                         \
+       }
+
+static struct meson_ee_pwrc_top_domain sm1_pwrc_vpu = SM1_EE_PD(8);
+static struct meson_ee_pwrc_top_domain sm1_pwrc_nna = SM1_EE_PD(16);
+static struct meson_ee_pwrc_top_domain sm1_pwrc_usb = SM1_EE_PD(17);
+static struct meson_ee_pwrc_top_domain sm1_pwrc_pci = SM1_EE_PD(18);
+static struct meson_ee_pwrc_top_domain sm1_pwrc_ge2d = SM1_EE_PD(19);
+
+static struct meson_ee_pwrc_top_domain g12a_pwrc_nna = {
+       .sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0,
+       .sleep_mask = BIT(16) | BIT(17),
+       .iso_reg = GX_AO_RTI_GEN_PWR_ISO0,
+       .iso_mask = BIT(16) | BIT(17),
+};
+
+/* Memory PD Domains */
+
+#define VPU_MEMPD(__reg)                                       \
+       { __reg, GENMASK(1, 0) },                               \
+       { __reg, GENMASK(3, 2) },                               \
+       { __reg, GENMASK(5, 4) },                               \
+       { __reg, GENMASK(7, 6) },                               \
+       { __reg, GENMASK(9, 8) },                               \
+       { __reg, GENMASK(11, 10) },                             \
+       { __reg, GENMASK(13, 12) },                             \
+       { __reg, GENMASK(15, 14) },                             \
+       { __reg, GENMASK(17, 16) },                             \
+       { __reg, GENMASK(19, 18) },                             \
+       { __reg, GENMASK(21, 20) },                             \
+       { __reg, GENMASK(23, 22) },                             \
+       { __reg, GENMASK(25, 24) },                             \
+       { __reg, GENMASK(27, 26) },                             \
+       { __reg, GENMASK(29, 28) },                             \
+       { __reg, GENMASK(31, 30) }
+
+#define VPU_HHI_MEMPD(__reg)                                   \
+       { __reg, BIT(8) },                                      \
+       { __reg, BIT(9) },                                      \
+       { __reg, BIT(10) },                                     \
+       { __reg, BIT(11) },                                     \
+       { __reg, BIT(12) },                                     \
+       { __reg, BIT(13) },                                     \
+       { __reg, BIT(14) },                                     \
+       { __reg, BIT(15) }
+
+static struct meson_ee_pwrc_mem_domain axg_pwrc_mem_vpu[] = {
+       VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
+       VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
+};
+
+static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_vpu[] = {
+       VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
+       VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
+       VPU_MEMPD(HHI_VPU_MEM_PD_REG2),
+       VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
+};
+
+static struct meson_ee_pwrc_mem_domain gxbb_pwrc_mem_vpu[] = {
+       VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
+       VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
+       VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
+};
+
+static struct meson_ee_pwrc_mem_domain meson_pwrc_mem_eth[] = {
+       { HHI_MEM_PD_REG0, GENMASK(3, 2) },
+};
+
+static struct meson_ee_pwrc_mem_domain meson8_pwrc_audio_dsp_mem[] = {
+       { HHI_MEM_PD_REG0, GENMASK(1, 0) },
+};
+
+static struct meson_ee_pwrc_mem_domain meson8_pwrc_mem_vpu[] = {
+       VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
+       VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
+       VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
+};
+
+static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_vpu[] = {
+       VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
+       VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
+       VPU_MEMPD(HHI_VPU_MEM_PD_REG2),
+       VPU_MEMPD(HHI_VPU_MEM_PD_REG3),
+       { HHI_VPU_MEM_PD_REG4, GENMASK(1, 0) },
+       { HHI_VPU_MEM_PD_REG4, GENMASK(3, 2) },
+       { HHI_VPU_MEM_PD_REG4, GENMASK(5, 4) },
+       { HHI_VPU_MEM_PD_REG4, GENMASK(7, 6) },
+       VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
+};
+
+static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_nna[] = {
+       { HHI_NANOQ_MEM_PD_REG0, 0xff },
+       { HHI_NANOQ_MEM_PD_REG1, 0xff },
+};
+
+static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_usb[] = {
+       { HHI_MEM_PD_REG0, GENMASK(31, 30) },
+};
+
+static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_pcie[] = {
+       { HHI_MEM_PD_REG0, GENMASK(29, 26) },
+};
+
+static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_ge2d[] = {
+       { HHI_MEM_PD_REG0, GENMASK(25, 18) },
+};
+
+static struct meson_ee_pwrc_mem_domain axg_pwrc_mem_audio[] = {
+       { HHI_MEM_PD_REG0, GENMASK(5, 4) },
+};
+
+static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_audio[] = {
+       { HHI_MEM_PD_REG0, GENMASK(5, 4) },
+       { HHI_AUDIO_MEM_PD_REG0, GENMASK(1, 0) },
+       { HHI_AUDIO_MEM_PD_REG0, GENMASK(3, 2) },
+       { HHI_AUDIO_MEM_PD_REG0, GENMASK(5, 4) },
+       { HHI_AUDIO_MEM_PD_REG0, GENMASK(7, 6) },
+       { HHI_AUDIO_MEM_PD_REG0, GENMASK(13, 12) },
+       { HHI_AUDIO_MEM_PD_REG0, GENMASK(15, 14) },
+       { HHI_AUDIO_MEM_PD_REG0, GENMASK(17, 16) },
+       { HHI_AUDIO_MEM_PD_REG0, GENMASK(19, 18) },
+       { HHI_AUDIO_MEM_PD_REG0, GENMASK(21, 20) },
+       { HHI_AUDIO_MEM_PD_REG0, GENMASK(23, 22) },
+       { HHI_AUDIO_MEM_PD_REG0, GENMASK(25, 24) },
+       { HHI_AUDIO_MEM_PD_REG0, GENMASK(27, 26) },
+};
+
+static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_nna[] = {
+       { G12A_HHI_NANOQ_MEM_PD_REG0, GENMASK(31, 0) },
+       { G12A_HHI_NANOQ_MEM_PD_REG1, GENMASK(23, 0) },
+};
+
+#define VPU_PD(__name, __top_pd, __mem, __is_pwr_off, __resets, __clks)        \
+       {                                                               \
+               .name = __name,                                         \
+               .reset_names_count = __resets,                          \
+               .clk_names_count = __clks,                              \
+               .top_pd = __top_pd,                                     \
+               .mem_pd_count = ARRAY_SIZE(__mem),                      \
+               .mem_pd = __mem,                                        \
+               .is_powered_off = __is_pwr_off,                         \
+       }
+
+#define TOP_PD(__name, __top_pd, __mem, __is_pwr_off)                  \
+       {                                                               \
+               .name = __name,                                         \
+               .top_pd = __top_pd,                                     \
+               .mem_pd_count = ARRAY_SIZE(__mem),                      \
+               .mem_pd = __mem,                                        \
+               .is_powered_off = __is_pwr_off,                         \
+       }
+
+#define MEM_PD(__name, __mem)                                          \
+       TOP_PD(__name, NULL, __mem, NULL)
+
+static bool pwrc_ee_is_powered_off(struct meson_ee_pwrc_domain *pwrc_domain);
+
+static struct meson_ee_pwrc_domain_desc axg_pwrc_domains[] = {
+       [PWRC_AXG_VPU_ID]  = VPU_PD("VPU", &gx_pwrc_vpu, axg_pwrc_mem_vpu,
+                                    pwrc_ee_is_powered_off, 5, 2),
+       [PWRC_AXG_ETHERNET_MEM_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
+       [PWRC_AXG_AUDIO_ID] = MEM_PD("AUDIO", axg_pwrc_mem_audio),
+};
+
+static struct meson_ee_pwrc_domain_desc g12a_pwrc_domains[] = {
+       [PWRC_G12A_VPU_ID]  = VPU_PD("VPU", &gx_pwrc_vpu, g12a_pwrc_mem_vpu,
+                                    pwrc_ee_is_powered_off, 11, 2),
+       [PWRC_G12A_ETH_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
+       [PWRC_G12A_NNA_ID] = TOP_PD("NNA", &g12a_pwrc_nna, g12a_pwrc_mem_nna,
+                                   pwrc_ee_is_powered_off),
+};
+
+static struct meson_ee_pwrc_domain_desc gxbb_pwrc_domains[] = {
+       [PWRC_GXBB_VPU_ID]  = VPU_PD("VPU", &gx_pwrc_vpu, gxbb_pwrc_mem_vpu,
+                                    pwrc_ee_is_powered_off, 12, 2),
+       [PWRC_GXBB_ETHERNET_MEM_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
+};
+
+static struct meson_ee_pwrc_domain_desc meson8_pwrc_domains[] = {
+       [PWRC_MESON8_VPU_ID]  = VPU_PD("VPU", &meson8_pwrc_vpu,
+                                      meson8_pwrc_mem_vpu,
+                                      pwrc_ee_is_powered_off, 0, 1),
+       [PWRC_MESON8_ETHERNET_MEM_ID] = MEM_PD("ETHERNET_MEM",
+                                              meson_pwrc_mem_eth),
+       [PWRC_MESON8_AUDIO_DSP_MEM_ID] = MEM_PD("AUDIO_DSP_MEM",
+                                               meson8_pwrc_audio_dsp_mem),
+};
+
+static struct meson_ee_pwrc_domain_desc meson8b_pwrc_domains[] = {
+       [PWRC_MESON8_VPU_ID]  = VPU_PD("VPU", &meson8_pwrc_vpu,
+                                      meson8_pwrc_mem_vpu,
+                                      pwrc_ee_is_powered_off, 11, 1),
+       [PWRC_MESON8_ETHERNET_MEM_ID] = MEM_PD("ETHERNET_MEM",
+                                              meson_pwrc_mem_eth),
+       [PWRC_MESON8_AUDIO_DSP_MEM_ID] = MEM_PD("AUDIO_DSP_MEM",
+                                               meson8_pwrc_audio_dsp_mem),
+};
+
+static struct meson_ee_pwrc_domain_desc sm1_pwrc_domains[] = {
+       [PWRC_SM1_VPU_ID]  = VPU_PD("VPU", &sm1_pwrc_vpu, sm1_pwrc_mem_vpu,
+                                   pwrc_ee_is_powered_off, 11, 2),
+       [PWRC_SM1_NNA_ID]  = TOP_PD("NNA", &sm1_pwrc_nna, sm1_pwrc_mem_nna,
+                                   pwrc_ee_is_powered_off),
+       [PWRC_SM1_USB_ID]  = TOP_PD("USB", &sm1_pwrc_usb, sm1_pwrc_mem_usb,
+                                   pwrc_ee_is_powered_off),
+       [PWRC_SM1_PCIE_ID] = TOP_PD("PCI", &sm1_pwrc_pci, sm1_pwrc_mem_pcie,
+                                   pwrc_ee_is_powered_off),
+       [PWRC_SM1_GE2D_ID] = TOP_PD("GE2D", &sm1_pwrc_ge2d, sm1_pwrc_mem_ge2d,
+                                   pwrc_ee_is_powered_off),
+       [PWRC_SM1_AUDIO_ID] = MEM_PD("AUDIO", sm1_pwrc_mem_audio),
+       [PWRC_SM1_ETH_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
+};
+
+struct meson_ee_pwrc_domain {
+       struct generic_pm_domain base;
+       bool enabled;
+       struct meson_ee_pwrc *pwrc;
+       struct meson_ee_pwrc_domain_desc desc;
+       struct clk_bulk_data *clks;
+       int num_clks;
+       struct reset_control *rstc;
+       int num_rstc;
+};
+
+struct meson_ee_pwrc {
+       struct regmap *regmap_ao;
+       struct regmap *regmap_hhi;
+       struct meson_ee_pwrc_domain *domains;
+       struct genpd_onecell_data xlate;
+};
+
+static bool pwrc_ee_is_powered_off(struct meson_ee_pwrc_domain *pwrc_domain)
+{
+       u32 reg;
+
+       regmap_read(pwrc_domain->pwrc->regmap_ao,
+                   pwrc_domain->desc.top_pd->sleep_reg, &reg);
+
+       return (reg & pwrc_domain->desc.top_pd->sleep_mask);
+}
+
+static int meson_ee_pwrc_off(struct generic_pm_domain *domain)
+{
+       struct meson_ee_pwrc_domain *pwrc_domain =
+               container_of(domain, struct meson_ee_pwrc_domain, base);
+       int i;
+
+       if (pwrc_domain->desc.top_pd)
+               regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
+                                  pwrc_domain->desc.top_pd->sleep_reg,
+                                  pwrc_domain->desc.top_pd->sleep_mask,
+                                  pwrc_domain->desc.top_pd->sleep_mask);
+       udelay(20);
+
+       for (i = 0 ; i < pwrc_domain->desc.mem_pd_count ; ++i)
+               regmap_update_bits(pwrc_domain->pwrc->regmap_hhi,
+                                  pwrc_domain->desc.mem_pd[i].reg,
+                                  pwrc_domain->desc.mem_pd[i].mask,
+                                  pwrc_domain->desc.mem_pd[i].mask);
+
+       udelay(20);
+
+       if (pwrc_domain->desc.top_pd)
+               regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
+                                  pwrc_domain->desc.top_pd->iso_reg,
+                                  pwrc_domain->desc.top_pd->iso_mask,
+                                  pwrc_domain->desc.top_pd->iso_mask);
+
+       if (pwrc_domain->num_clks) {
+               msleep(20);
+               clk_bulk_disable_unprepare(pwrc_domain->num_clks,
+                                          pwrc_domain->clks);
+       }
+
+       return 0;
+}
+
+static int meson_ee_pwrc_on(struct generic_pm_domain *domain)
+{
+       struct meson_ee_pwrc_domain *pwrc_domain =
+               container_of(domain, struct meson_ee_pwrc_domain, base);
+       int i, ret;
+
+       if (pwrc_domain->desc.top_pd)
+               regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
+                                  pwrc_domain->desc.top_pd->sleep_reg,
+                                  pwrc_domain->desc.top_pd->sleep_mask, 0);
+       udelay(20);
+
+       for (i = 0 ; i < pwrc_domain->desc.mem_pd_count ; ++i)
+               regmap_update_bits(pwrc_domain->pwrc->regmap_hhi,
+                                  pwrc_domain->desc.mem_pd[i].reg,
+                                  pwrc_domain->desc.mem_pd[i].mask, 0);
+
+       udelay(20);
+
+       ret = reset_control_assert(pwrc_domain->rstc);
+       if (ret)
+               return ret;
+
+       if (pwrc_domain->desc.top_pd)
+               regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
+                                  pwrc_domain->desc.top_pd->iso_reg,
+                                  pwrc_domain->desc.top_pd->iso_mask, 0);
+
+       ret = reset_control_deassert(pwrc_domain->rstc);
+       if (ret)
+               return ret;
+
+       return clk_bulk_prepare_enable(pwrc_domain->num_clks,
+                                      pwrc_domain->clks);
+}
+
+static int meson_ee_pwrc_init_domain(struct platform_device *pdev,
+                                    struct meson_ee_pwrc *pwrc,
+                                    struct meson_ee_pwrc_domain *dom)
+{
+       int ret;
+
+       dom->pwrc = pwrc;
+       dom->num_rstc = dom->desc.reset_names_count;
+       dom->num_clks = dom->desc.clk_names_count;
+
+       if (dom->num_rstc) {
+               int count = reset_control_get_count(&pdev->dev);
+
+               if (count != dom->num_rstc)
+                       dev_warn(&pdev->dev, "Invalid resets count %d for domain %s\n",
+                                count, dom->desc.name);
+
+               dom->rstc = devm_reset_control_array_get_exclusive(&pdev->dev);
+               if (IS_ERR(dom->rstc))
+                       return PTR_ERR(dom->rstc);
+       }
+
+       if (dom->num_clks) {
+               int ret = devm_clk_bulk_get_all(&pdev->dev, &dom->clks);
+               if (ret < 0)
+                       return ret;
+
+               if (dom->num_clks != ret) {
+                       dev_warn(&pdev->dev, "Invalid clocks count %d for domain %s\n",
+                                ret, dom->desc.name);
+                       dom->num_clks = ret;
+               }
+       }
+
+       dom->base.name = dom->desc.name;
+       dom->base.power_on = meson_ee_pwrc_on;
+       dom->base.power_off = meson_ee_pwrc_off;
+
+       /*
+         * TOFIX: This is a special case for the VPU power domain, which can
+        * be enabled previously by the bootloader. In this case the VPU
+         * pipeline may be functional but no driver maybe never attach
+         * to this power domain, and if the domain is disabled it could
+         * cause system errors. This is why the pm_domain_always_on_gov
+         * is used here.
+         * For the same reason, the clocks should be enabled in case
+         * we need to power the domain off, otherwise the internal clocks
+         * prepare/enable counters won't be in sync.
+         */
+       if (dom->num_clks && dom->desc.is_powered_off && !dom->desc.is_powered_off(dom)) {
+               ret = clk_bulk_prepare_enable(dom->num_clks, dom->clks);
+               if (ret)
+                       return ret;
+
+               dom->base.flags = GENPD_FLAG_ALWAYS_ON;
+               ret = pm_genpd_init(&dom->base, NULL, false);
+               if (ret)
+                       return ret;
+       } else {
+               ret = pm_genpd_init(&dom->base, NULL,
+                                   (dom->desc.is_powered_off ?
+                                    dom->desc.is_powered_off(dom) : true));
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int meson_ee_pwrc_probe(struct platform_device *pdev)
+{
+       const struct meson_ee_pwrc_domain_data *match;
+       struct regmap *regmap_ao, *regmap_hhi;
+       struct device_node *parent_np;
+       struct meson_ee_pwrc *pwrc;
+       int i, ret;
+
+       match = of_device_get_match_data(&pdev->dev);
+       if (!match) {
+               dev_err(&pdev->dev, "failed to get match data\n");
+               return -ENODEV;
+       }
+
+       pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL);
+       if (!pwrc)
+               return -ENOMEM;
+
+       pwrc->xlate.domains = devm_kcalloc(&pdev->dev, match->count,
+                                          sizeof(*pwrc->xlate.domains),
+                                          GFP_KERNEL);
+       if (!pwrc->xlate.domains)
+               return -ENOMEM;
+
+       pwrc->domains = devm_kcalloc(&pdev->dev, match->count,
+                                    sizeof(*pwrc->domains), GFP_KERNEL);
+       if (!pwrc->domains)
+               return -ENOMEM;
+
+       pwrc->xlate.num_domains = match->count;
+
+       parent_np = of_get_parent(pdev->dev.of_node);
+       regmap_hhi = syscon_node_to_regmap(parent_np);
+       of_node_put(parent_np);
+       if (IS_ERR(regmap_hhi)) {
+               dev_err(&pdev->dev, "failed to get HHI regmap\n");
+               return PTR_ERR(regmap_hhi);
+       }
+
+       regmap_ao = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+                                                   "amlogic,ao-sysctrl");
+       if (IS_ERR(regmap_ao)) {
+               dev_err(&pdev->dev, "failed to get AO regmap\n");
+               return PTR_ERR(regmap_ao);
+       }
+
+       pwrc->regmap_ao = regmap_ao;
+       pwrc->regmap_hhi = regmap_hhi;
+
+       platform_set_drvdata(pdev, pwrc);
+
+       for (i = 0 ; i < match->count ; ++i) {
+               struct meson_ee_pwrc_domain *dom = &pwrc->domains[i];
+
+               memcpy(&dom->desc, &match->domains[i], sizeof(dom->desc));
+
+               ret = meson_ee_pwrc_init_domain(pdev, pwrc, dom);
+               if (ret)
+                       return ret;
+
+               pwrc->xlate.domains[i] = &dom->base;
+       }
+
+       return of_genpd_add_provider_onecell(pdev->dev.of_node, &pwrc->xlate);
+}
+
+static void meson_ee_pwrc_shutdown(struct platform_device *pdev)
+{
+       struct meson_ee_pwrc *pwrc = platform_get_drvdata(pdev);
+       int i;
+
+       for (i = 0 ; i < pwrc->xlate.num_domains ; ++i) {
+               struct meson_ee_pwrc_domain *dom = &pwrc->domains[i];
+
+               if (dom->desc.is_powered_off && !dom->desc.is_powered_off(dom))
+                       meson_ee_pwrc_off(&dom->base);
+       }
+}
+
+static struct meson_ee_pwrc_domain_data meson_ee_g12a_pwrc_data = {
+       .count = ARRAY_SIZE(g12a_pwrc_domains),
+       .domains = g12a_pwrc_domains,
+};
+
+static struct meson_ee_pwrc_domain_data meson_ee_axg_pwrc_data = {
+       .count = ARRAY_SIZE(axg_pwrc_domains),
+       .domains = axg_pwrc_domains,
+};
+
+static struct meson_ee_pwrc_domain_data meson_ee_gxbb_pwrc_data = {
+       .count = ARRAY_SIZE(gxbb_pwrc_domains),
+       .domains = gxbb_pwrc_domains,
+};
+
+static struct meson_ee_pwrc_domain_data meson_ee_m8_pwrc_data = {
+       .count = ARRAY_SIZE(meson8_pwrc_domains),
+       .domains = meson8_pwrc_domains,
+};
+
+static struct meson_ee_pwrc_domain_data meson_ee_m8b_pwrc_data = {
+       .count = ARRAY_SIZE(meson8b_pwrc_domains),
+       .domains = meson8b_pwrc_domains,
+};
+
+static struct meson_ee_pwrc_domain_data meson_ee_sm1_pwrc_data = {
+       .count = ARRAY_SIZE(sm1_pwrc_domains),
+       .domains = sm1_pwrc_domains,
+};
+
+static const struct of_device_id meson_ee_pwrc_match_table[] = {
+       {
+               .compatible = "amlogic,meson8-pwrc",
+               .data = &meson_ee_m8_pwrc_data,
+       },
+       {
+               .compatible = "amlogic,meson8b-pwrc",
+               .data = &meson_ee_m8b_pwrc_data,
+       },
+       {
+               .compatible = "amlogic,meson8m2-pwrc",
+               .data = &meson_ee_m8b_pwrc_data,
+       },
+       {
+               .compatible = "amlogic,meson-axg-pwrc",
+               .data = &meson_ee_axg_pwrc_data,
+       },
+       {
+               .compatible = "amlogic,meson-gxbb-pwrc",
+               .data = &meson_ee_gxbb_pwrc_data,
+       },
+       {
+               .compatible = "amlogic,meson-g12a-pwrc",
+               .data = &meson_ee_g12a_pwrc_data,
+       },
+       {
+               .compatible = "amlogic,meson-sm1-pwrc",
+               .data = &meson_ee_sm1_pwrc_data,
+       },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, meson_ee_pwrc_match_table);
+
+static struct platform_driver meson_ee_pwrc_driver = {
+       .probe = meson_ee_pwrc_probe,
+       .shutdown = meson_ee_pwrc_shutdown,
+       .driver = {
+               .name           = "meson_ee_pwrc",
+               .of_match_table = meson_ee_pwrc_match_table,
+       },
+};
+module_platform_driver(meson_ee_pwrc_driver);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pmdomain/amlogic/meson-gx-pwrc-vpu.c b/drivers/pmdomain/amlogic/meson-gx-pwrc-vpu.c
new file mode 100644 (file)
index 0000000..33df520
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 2017 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/bitfield.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/reset.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+
+/* AO Offsets */
+
+#define AO_RTI_GEN_PWR_SLEEP0          (0x3a << 2)
+
+#define GEN_PWR_VPU_HDMI               BIT(8)
+#define GEN_PWR_VPU_HDMI_ISO           BIT(9)
+
+/* HHI Offsets */
+
+#define HHI_MEM_PD_REG0                        (0x40 << 2)
+#define HHI_VPU_MEM_PD_REG0            (0x41 << 2)
+#define HHI_VPU_MEM_PD_REG1            (0x42 << 2)
+#define HHI_VPU_MEM_PD_REG2            (0x4d << 2)
+
+struct meson_gx_pwrc_vpu {
+       struct generic_pm_domain genpd;
+       struct regmap *regmap_ao;
+       struct regmap *regmap_hhi;
+       struct reset_control *rstc;
+       struct clk *vpu_clk;
+       struct clk *vapb_clk;
+};
+
+static inline
+struct meson_gx_pwrc_vpu *genpd_to_pd(struct generic_pm_domain *d)
+{
+       return container_of(d, struct meson_gx_pwrc_vpu, genpd);
+}
+
+static int meson_gx_pwrc_vpu_power_off(struct generic_pm_domain *genpd)
+{
+       struct meson_gx_pwrc_vpu *pd = genpd_to_pd(genpd);
+       int i;
+
+       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+                          GEN_PWR_VPU_HDMI_ISO, GEN_PWR_VPU_HDMI_ISO);
+       udelay(20);
+
+       /* Power Down Memories */
+       for (i = 0; i < 32; i += 2) {
+               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0,
+                                  0x3 << i, 0x3 << i);
+               udelay(5);
+       }
+       for (i = 0; i < 32; i += 2) {
+               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1,
+                                  0x3 << i, 0x3 << i);
+               udelay(5);
+       }
+       for (i = 8; i < 16; i++) {
+               regmap_update_bits(pd->regmap_hhi, HHI_MEM_PD_REG0,
+                                  BIT(i), BIT(i));
+               udelay(5);
+       }
+       udelay(20);
+
+       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+                          GEN_PWR_VPU_HDMI, GEN_PWR_VPU_HDMI);
+
+       msleep(20);
+
+       clk_disable_unprepare(pd->vpu_clk);
+       clk_disable_unprepare(pd->vapb_clk);
+
+       return 0;
+}
+
+static int meson_g12a_pwrc_vpu_power_off(struct generic_pm_domain *genpd)
+{
+       struct meson_gx_pwrc_vpu *pd = genpd_to_pd(genpd);
+       int i;
+
+       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+                          GEN_PWR_VPU_HDMI_ISO, GEN_PWR_VPU_HDMI_ISO);
+       udelay(20);
+
+       /* Power Down Memories */
+       for (i = 0; i < 32; i += 2) {
+               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0,
+                                  0x3 << i, 0x3 << i);
+               udelay(5);
+       }
+       for (i = 0; i < 32; i += 2) {
+               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1,
+                                  0x3 << i, 0x3 << i);
+               udelay(5);
+       }
+       for (i = 0; i < 32; i += 2) {
+               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG2,
+                                  0x3 << i, 0x3 << i);
+               udelay(5);
+       }
+       for (i = 8; i < 16; i++) {
+               regmap_update_bits(pd->regmap_hhi, HHI_MEM_PD_REG0,
+                                  BIT(i), BIT(i));
+               udelay(5);
+       }
+       udelay(20);
+
+       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+                          GEN_PWR_VPU_HDMI, GEN_PWR_VPU_HDMI);
+
+       msleep(20);
+
+       clk_disable_unprepare(pd->vpu_clk);
+       clk_disable_unprepare(pd->vapb_clk);
+
+       return 0;
+}
+
+static int meson_gx_pwrc_vpu_setup_clk(struct meson_gx_pwrc_vpu *pd)
+{
+       int ret;
+
+       ret = clk_prepare_enable(pd->vpu_clk);
+       if (ret)
+               return ret;
+
+       ret = clk_prepare_enable(pd->vapb_clk);
+       if (ret)
+               clk_disable_unprepare(pd->vpu_clk);
+
+       return ret;
+}
+
+static int meson_gx_pwrc_vpu_power_on(struct generic_pm_domain *genpd)
+{
+       struct meson_gx_pwrc_vpu *pd = genpd_to_pd(genpd);
+       int ret;
+       int i;
+
+       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+                          GEN_PWR_VPU_HDMI, 0);
+       udelay(20);
+
+       /* Power Up Memories */
+       for (i = 0; i < 32; i += 2) {
+               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0,
+                                  0x3 << i, 0);
+               udelay(5);
+       }
+
+       for (i = 0; i < 32; i += 2) {
+               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1,
+                                  0x3 << i, 0);
+               udelay(5);
+       }
+
+       for (i = 8; i < 16; i++) {
+               regmap_update_bits(pd->regmap_hhi, HHI_MEM_PD_REG0,
+                                  BIT(i), 0);
+               udelay(5);
+       }
+       udelay(20);
+
+       ret = reset_control_assert(pd->rstc);
+       if (ret)
+               return ret;
+
+       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+                          GEN_PWR_VPU_HDMI_ISO, 0);
+
+       ret = reset_control_deassert(pd->rstc);
+       if (ret)
+               return ret;
+
+       ret = meson_gx_pwrc_vpu_setup_clk(pd);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int meson_g12a_pwrc_vpu_power_on(struct generic_pm_domain *genpd)
+{
+       struct meson_gx_pwrc_vpu *pd = genpd_to_pd(genpd);
+       int ret;
+       int i;
+
+       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+                          GEN_PWR_VPU_HDMI, 0);
+       udelay(20);
+
+       /* Power Up Memories */
+       for (i = 0; i < 32; i += 2) {
+               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0,
+                                  0x3 << i, 0);
+               udelay(5);
+       }
+
+       for (i = 0; i < 32; i += 2) {
+               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1,
+                                  0x3 << i, 0);
+               udelay(5);
+       }
+
+       for (i = 0; i < 32; i += 2) {
+               regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG2,
+                                  0x3 << i, 0);
+               udelay(5);
+       }
+
+       for (i = 8; i < 16; i++) {
+               regmap_update_bits(pd->regmap_hhi, HHI_MEM_PD_REG0,
+                                  BIT(i), 0);
+               udelay(5);
+       }
+       udelay(20);
+
+       ret = reset_control_assert(pd->rstc);
+       if (ret)
+               return ret;
+
+       regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+                          GEN_PWR_VPU_HDMI_ISO, 0);
+
+       ret = reset_control_deassert(pd->rstc);
+       if (ret)
+               return ret;
+
+       ret = meson_gx_pwrc_vpu_setup_clk(pd);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static bool meson_gx_pwrc_vpu_get_power(struct meson_gx_pwrc_vpu *pd)
+{
+       u32 reg;
+
+       regmap_read(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, &reg);
+
+       return (reg & GEN_PWR_VPU_HDMI);
+}
+
+static struct meson_gx_pwrc_vpu vpu_hdmi_pd = {
+       .genpd = {
+               .name = "vpu_hdmi",
+               .power_off = meson_gx_pwrc_vpu_power_off,
+               .power_on = meson_gx_pwrc_vpu_power_on,
+       },
+};
+
+static struct meson_gx_pwrc_vpu vpu_hdmi_pd_g12a = {
+       .genpd = {
+               .name = "vpu_hdmi",
+               .power_off = meson_g12a_pwrc_vpu_power_off,
+               .power_on = meson_g12a_pwrc_vpu_power_on,
+       },
+};
+
+static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
+{
+       const struct meson_gx_pwrc_vpu *vpu_pd_match;
+       struct regmap *regmap_ao, *regmap_hhi;
+       struct meson_gx_pwrc_vpu *vpu_pd;
+       struct device_node *parent_np;
+       struct reset_control *rstc;
+       struct clk *vpu_clk;
+       struct clk *vapb_clk;
+       bool powered_off;
+       int ret;
+
+       vpu_pd_match = of_device_get_match_data(&pdev->dev);
+       if (!vpu_pd_match) {
+               dev_err(&pdev->dev, "failed to get match data\n");
+               return -ENODEV;
+       }
+
+       vpu_pd = devm_kzalloc(&pdev->dev, sizeof(*vpu_pd), GFP_KERNEL);
+       if (!vpu_pd)
+               return -ENOMEM;
+
+       memcpy(vpu_pd, vpu_pd_match, sizeof(*vpu_pd));
+
+       parent_np = of_get_parent(pdev->dev.of_node);
+       regmap_ao = syscon_node_to_regmap(parent_np);
+       of_node_put(parent_np);
+       if (IS_ERR(regmap_ao)) {
+               dev_err(&pdev->dev, "failed to get regmap\n");
+               return PTR_ERR(regmap_ao);
+       }
+
+       regmap_hhi = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+                                                    "amlogic,hhi-sysctrl");
+       if (IS_ERR(regmap_hhi)) {
+               dev_err(&pdev->dev, "failed to get HHI regmap\n");
+               return PTR_ERR(regmap_hhi);
+       }
+
+       rstc = devm_reset_control_array_get_exclusive(&pdev->dev);
+       if (IS_ERR(rstc))
+               return dev_err_probe(&pdev->dev, PTR_ERR(rstc),
+                                    "failed to get reset lines\n");
+
+       vpu_clk = devm_clk_get(&pdev->dev, "vpu");
+       if (IS_ERR(vpu_clk)) {
+               dev_err(&pdev->dev, "vpu clock request failed\n");
+               return PTR_ERR(vpu_clk);
+       }
+
+       vapb_clk = devm_clk_get(&pdev->dev, "vapb");
+       if (IS_ERR(vapb_clk)) {
+               dev_err(&pdev->dev, "vapb clock request failed\n");
+               return PTR_ERR(vapb_clk);
+       }
+
+       vpu_pd->regmap_ao = regmap_ao;
+       vpu_pd->regmap_hhi = regmap_hhi;
+       vpu_pd->rstc = rstc;
+       vpu_pd->vpu_clk = vpu_clk;
+       vpu_pd->vapb_clk = vapb_clk;
+
+       platform_set_drvdata(pdev, vpu_pd);
+
+       powered_off = meson_gx_pwrc_vpu_get_power(vpu_pd);
+
+       /* If already powered, sync the clock states */
+       if (!powered_off) {
+               ret = meson_gx_pwrc_vpu_setup_clk(vpu_pd);
+               if (ret)
+                       return ret;
+       }
+
+       vpu_pd->genpd.flags = GENPD_FLAG_ALWAYS_ON;
+       pm_genpd_init(&vpu_pd->genpd, NULL, powered_off);
+
+       return of_genpd_add_provider_simple(pdev->dev.of_node,
+                                           &vpu_pd->genpd);
+}
+
+static void meson_gx_pwrc_vpu_shutdown(struct platform_device *pdev)
+{
+       struct meson_gx_pwrc_vpu *vpu_pd = platform_get_drvdata(pdev);
+       bool powered_off;
+
+       powered_off = meson_gx_pwrc_vpu_get_power(vpu_pd);
+       if (!powered_off)
+               vpu_pd->genpd.power_off(&vpu_pd->genpd);
+}
+
+static const struct of_device_id meson_gx_pwrc_vpu_match_table[] = {
+       { .compatible = "amlogic,meson-gx-pwrc-vpu", .data = &vpu_hdmi_pd },
+       {
+         .compatible = "amlogic,meson-g12a-pwrc-vpu",
+         .data = &vpu_hdmi_pd_g12a
+       },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, meson_gx_pwrc_vpu_match_table);
+
+static struct platform_driver meson_gx_pwrc_vpu_driver = {
+       .probe  = meson_gx_pwrc_vpu_probe,
+       .shutdown = meson_gx_pwrc_vpu_shutdown,
+       .driver = {
+               .name           = "meson_gx_pwrc_vpu",
+               .of_match_table = meson_gx_pwrc_vpu_match_table,
+       },
+};
+module_platform_driver(meson_gx_pwrc_vpu_driver);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pmdomain/amlogic/meson-secure-pwrc.c b/drivers/pmdomain/amlogic/meson-secure-pwrc.c
new file mode 100644 (file)
index 0000000..89c881c
--- /dev/null
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Amlogic, Inc.
+ * Author: Jianxin Pan <jianxin.pan@amlogic.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <dt-bindings/power/meson-a1-power.h>
+#include <dt-bindings/power/amlogic,c3-pwrc.h>
+#include <dt-bindings/power/meson-s4-power.h>
+#include <linux/arm-smccc.h>
+#include <linux/firmware/meson/meson_sm.h>
+#include <linux/module.h>
+
+#define PWRC_ON                1
+#define PWRC_OFF       0
+
+struct meson_secure_pwrc_domain {
+       struct generic_pm_domain base;
+       unsigned int index;
+       struct meson_secure_pwrc *pwrc;
+};
+
+struct meson_secure_pwrc {
+       struct meson_secure_pwrc_domain *domains;
+       struct genpd_onecell_data xlate;
+       struct meson_sm_firmware *fw;
+};
+
+struct meson_secure_pwrc_domain_desc {
+       unsigned int index;
+       unsigned int flags;
+       char *name;
+       bool (*is_off)(struct meson_secure_pwrc_domain *pwrc_domain);
+};
+
+struct meson_secure_pwrc_domain_data {
+       unsigned int count;
+       struct meson_secure_pwrc_domain_desc *domains;
+};
+
+static bool pwrc_secure_is_off(struct meson_secure_pwrc_domain *pwrc_domain)
+{
+       int is_off = 1;
+
+       if (meson_sm_call(pwrc_domain->pwrc->fw, SM_A1_PWRC_GET, &is_off,
+                         pwrc_domain->index, 0, 0, 0, 0) < 0)
+               pr_err("failed to get power domain status\n");
+
+       return is_off;
+}
+
+static int meson_secure_pwrc_off(struct generic_pm_domain *domain)
+{
+       int ret = 0;
+       struct meson_secure_pwrc_domain *pwrc_domain =
+               container_of(domain, struct meson_secure_pwrc_domain, base);
+
+       if (meson_sm_call(pwrc_domain->pwrc->fw, SM_A1_PWRC_SET, NULL,
+                         pwrc_domain->index, PWRC_OFF, 0, 0, 0) < 0) {
+               pr_err("failed to set power domain off\n");
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static int meson_secure_pwrc_on(struct generic_pm_domain *domain)
+{
+       int ret = 0;
+       struct meson_secure_pwrc_domain *pwrc_domain =
+               container_of(domain, struct meson_secure_pwrc_domain, base);
+
+       if (meson_sm_call(pwrc_domain->pwrc->fw, SM_A1_PWRC_SET, NULL,
+                         pwrc_domain->index, PWRC_ON, 0, 0, 0) < 0) {
+               pr_err("failed to set power domain on\n");
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+#define SEC_PD(__name, __flag)                 \
+[PWRC_##__name##_ID] =                         \
+{                                              \
+       .name = #__name,                        \
+       .index = PWRC_##__name##_ID,            \
+       .is_off = pwrc_secure_is_off,   \
+       .flags = __flag,                        \
+}
+
+static struct meson_secure_pwrc_domain_desc a1_pwrc_domains[] = {
+       SEC_PD(DSPA,    0),
+       SEC_PD(DSPB,    0),
+       /* UART should keep working in ATF after suspend and before resume */
+       SEC_PD(UART,    GENPD_FLAG_ALWAYS_ON),
+       /* DMC is for DDR PHY ana/dig and DMC, and should be always on */
+       SEC_PD(DMC,     GENPD_FLAG_ALWAYS_ON),
+       SEC_PD(I2C,     0),
+       SEC_PD(PSRAM,   0),
+       SEC_PD(ACODEC,  0),
+       SEC_PD(AUDIO,   0),
+       SEC_PD(OTP,     0),
+       SEC_PD(DMA,     GENPD_FLAG_ALWAYS_ON | GENPD_FLAG_IRQ_SAFE),
+       SEC_PD(SD_EMMC, 0),
+       SEC_PD(RAMA,    0),
+       /* SRAMB is used as ATF runtime memory, and should be always on */
+       SEC_PD(RAMB,    GENPD_FLAG_ALWAYS_ON),
+       SEC_PD(IR,      0),
+       SEC_PD(SPICC,   0),
+       SEC_PD(SPIFC,   0),
+       SEC_PD(USB,     0),
+       /* NIC is for the Arm NIC-400 interconnect, and should be always on */
+       SEC_PD(NIC,     GENPD_FLAG_ALWAYS_ON),
+       SEC_PD(PDMIN,   0),
+       SEC_PD(RSA,     0),
+};
+
+static struct meson_secure_pwrc_domain_desc c3_pwrc_domains[] = {
+       SEC_PD(C3_NNA,  0),
+       SEC_PD(C3_AUDIO,        GENPD_FLAG_ALWAYS_ON),
+       SEC_PD(C3_SDIOA,        GENPD_FLAG_ALWAYS_ON),
+       SEC_PD(C3_EMMC, GENPD_FLAG_ALWAYS_ON),
+       SEC_PD(C3_USB_COMB, GENPD_FLAG_ALWAYS_ON),
+       SEC_PD(C3_SDCARD,       GENPD_FLAG_ALWAYS_ON),
+       SEC_PD(C3_ETH,  GENPD_FLAG_ALWAYS_ON),
+       SEC_PD(C3_GE2D, GENPD_FLAG_ALWAYS_ON),
+       SEC_PD(C3_CVE,  GENPD_FLAG_ALWAYS_ON),
+       SEC_PD(C3_GDC_WRAP,     GENPD_FLAG_ALWAYS_ON),
+       SEC_PD(C3_ISP_TOP,              GENPD_FLAG_ALWAYS_ON),
+       SEC_PD(C3_MIPI_ISP_WRAP, GENPD_FLAG_ALWAYS_ON),
+       SEC_PD(C3_VCODEC,       0),
+};
+
+static struct meson_secure_pwrc_domain_desc s4_pwrc_domains[] = {
+       SEC_PD(S4_DOS_HEVC,     0),
+       SEC_PD(S4_DOS_VDEC,     0),
+       SEC_PD(S4_VPU_HDMI,     0),
+       SEC_PD(S4_USB_COMB,     0),
+       SEC_PD(S4_GE2D,         0),
+       /* ETH is for ethernet online wakeup, and should be always on */
+       SEC_PD(S4_ETH,          GENPD_FLAG_ALWAYS_ON),
+       SEC_PD(S4_DEMOD,        0),
+       SEC_PD(S4_AUDIO,        0),
+};
+
+static int meson_secure_pwrc_probe(struct platform_device *pdev)
+{
+       int i;
+       struct device_node *sm_np;
+       struct meson_secure_pwrc *pwrc;
+       const struct meson_secure_pwrc_domain_data *match;
+
+       match = of_device_get_match_data(&pdev->dev);
+       if (!match) {
+               dev_err(&pdev->dev, "failed to get match data\n");
+               return -ENODEV;
+       }
+
+       sm_np = of_find_compatible_node(NULL, NULL, "amlogic,meson-gxbb-sm");
+       if (!sm_np) {
+               dev_err(&pdev->dev, "no secure-monitor node\n");
+               return -ENODEV;
+       }
+
+       pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL);
+       if (!pwrc) {
+               of_node_put(sm_np);
+               return -ENOMEM;
+       }
+
+       pwrc->fw = meson_sm_get(sm_np);
+       of_node_put(sm_np);
+       if (!pwrc->fw)
+               return -EPROBE_DEFER;
+
+       pwrc->xlate.domains = devm_kcalloc(&pdev->dev, match->count,
+                                          sizeof(*pwrc->xlate.domains),
+                                          GFP_KERNEL);
+       if (!pwrc->xlate.domains)
+               return -ENOMEM;
+
+       pwrc->domains = devm_kcalloc(&pdev->dev, match->count,
+                                    sizeof(*pwrc->domains), GFP_KERNEL);
+       if (!pwrc->domains)
+               return -ENOMEM;
+
+       pwrc->xlate.num_domains = match->count;
+       platform_set_drvdata(pdev, pwrc);
+
+       for (i = 0 ; i < match->count ; ++i) {
+               struct meson_secure_pwrc_domain *dom = &pwrc->domains[i];
+
+               if (!match->domains[i].name)
+                       continue;
+
+               dom->pwrc = pwrc;
+               dom->index = match->domains[i].index;
+               dom->base.name = match->domains[i].name;
+               dom->base.flags = match->domains[i].flags;
+               dom->base.power_on = meson_secure_pwrc_on;
+               dom->base.power_off = meson_secure_pwrc_off;
+
+               pm_genpd_init(&dom->base, NULL, match->domains[i].is_off(dom));
+
+               pwrc->xlate.domains[i] = &dom->base;
+       }
+
+       return of_genpd_add_provider_onecell(pdev->dev.of_node, &pwrc->xlate);
+}
+
+static struct meson_secure_pwrc_domain_data meson_secure_a1_pwrc_data = {
+       .domains = a1_pwrc_domains,
+       .count = ARRAY_SIZE(a1_pwrc_domains),
+};
+
+static struct meson_secure_pwrc_domain_data amlogic_secure_c3_pwrc_data = {
+       .domains = c3_pwrc_domains,
+       .count = ARRAY_SIZE(c3_pwrc_domains),
+};
+
+static struct meson_secure_pwrc_domain_data meson_secure_s4_pwrc_data = {
+       .domains = s4_pwrc_domains,
+       .count = ARRAY_SIZE(s4_pwrc_domains),
+};
+
+static const struct of_device_id meson_secure_pwrc_match_table[] = {
+       {
+               .compatible = "amlogic,meson-a1-pwrc",
+               .data = &meson_secure_a1_pwrc_data,
+       },
+       {
+               .compatible = "amlogic,c3-pwrc",
+               .data = &amlogic_secure_c3_pwrc_data,
+       },
+       {
+               .compatible = "amlogic,meson-s4-pwrc",
+               .data = &meson_secure_s4_pwrc_data,
+       },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, meson_secure_pwrc_match_table);
+
+static struct platform_driver meson_secure_pwrc_driver = {
+       .probe = meson_secure_pwrc_probe,
+       .driver = {
+               .name           = "meson_secure_pwrc",
+               .of_match_table = meson_secure_pwrc_match_table,
+       },
+};
+module_platform_driver(meson_secure_pwrc_driver);
+MODULE_LICENSE("Dual MIT/GPL");
diff --git a/drivers/pmdomain/apple/Makefile b/drivers/pmdomain/apple/Makefile
new file mode 100644 (file)
index 0000000..53665af
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_APPLE_PMGR_PWRSTATE)      += pmgr-pwrstate.o
diff --git a/drivers/pmdomain/apple/pmgr-pwrstate.c b/drivers/pmdomain/apple/pmgr-pwrstate.c
new file mode 100644 (file)
index 0000000..d62a776
--- /dev/null
@@ -0,0 +1,326 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Apple SoC PMGR device power state driver
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+#include <linux/bitops.h>
+#include <linux/bitfield.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/reset-controller.h>
+#include <linux/module.h>
+
+#define APPLE_PMGR_RESET        BIT(31)
+#define APPLE_PMGR_AUTO_ENABLE  BIT(28)
+#define APPLE_PMGR_PS_AUTO      GENMASK(27, 24)
+#define APPLE_PMGR_PS_MIN       GENMASK(19, 16)
+#define APPLE_PMGR_PARENT_OFF   BIT(11)
+#define APPLE_PMGR_DEV_DISABLE  BIT(10)
+#define APPLE_PMGR_WAS_CLKGATED BIT(9)
+#define APPLE_PMGR_WAS_PWRGATED BIT(8)
+#define APPLE_PMGR_PS_ACTUAL    GENMASK(7, 4)
+#define APPLE_PMGR_PS_TARGET    GENMASK(3, 0)
+
+#define APPLE_PMGR_FLAGS        (APPLE_PMGR_WAS_CLKGATED | APPLE_PMGR_WAS_PWRGATED)
+
+#define APPLE_PMGR_PS_ACTIVE    0xf
+#define APPLE_PMGR_PS_CLKGATE   0x4
+#define APPLE_PMGR_PS_PWRGATE   0x0
+
+#define APPLE_PMGR_PS_SET_TIMEOUT 100
+#define APPLE_PMGR_RESET_TIME 1
+
+struct apple_pmgr_ps {
+       struct device *dev;
+       struct generic_pm_domain genpd;
+       struct reset_controller_dev rcdev;
+       struct regmap *regmap;
+       u32 offset;
+       u32 min_state;
+};
+
+#define genpd_to_apple_pmgr_ps(_genpd) container_of(_genpd, struct apple_pmgr_ps, genpd)
+#define rcdev_to_apple_pmgr_ps(_rcdev) container_of(_rcdev, struct apple_pmgr_ps, rcdev)
+
+static int apple_pmgr_ps_set(struct generic_pm_domain *genpd, u32 pstate, bool auto_enable)
+{
+       int ret;
+       struct apple_pmgr_ps *ps = genpd_to_apple_pmgr_ps(genpd);
+       u32 reg;
+
+       ret = regmap_read(ps->regmap, ps->offset, &reg);
+       if (ret < 0)
+               return ret;
+
+       /* Resets are synchronous, and only work if the device is powered and clocked. */
+       if (reg & APPLE_PMGR_RESET && pstate != APPLE_PMGR_PS_ACTIVE)
+               dev_err(ps->dev, "PS %s: powering off with RESET active\n",
+                       genpd->name);
+
+       reg &= ~(APPLE_PMGR_AUTO_ENABLE | APPLE_PMGR_FLAGS | APPLE_PMGR_PS_TARGET);
+       reg |= FIELD_PREP(APPLE_PMGR_PS_TARGET, pstate);
+
+       dev_dbg(ps->dev, "PS %s: pwrstate = 0x%x: 0x%x\n", genpd->name, pstate, reg);
+
+       regmap_write(ps->regmap, ps->offset, reg);
+
+       ret = regmap_read_poll_timeout_atomic(
+               ps->regmap, ps->offset, reg,
+               (FIELD_GET(APPLE_PMGR_PS_ACTUAL, reg) == pstate), 1,
+               APPLE_PMGR_PS_SET_TIMEOUT);
+       if (ret < 0)
+               dev_err(ps->dev, "PS %s: Failed to reach power state 0x%x (now: 0x%x)\n",
+                       genpd->name, pstate, reg);
+
+       if (auto_enable) {
+               /* Not all devices implement this; this is a no-op where not implemented. */
+               reg &= ~APPLE_PMGR_FLAGS;
+               reg |= APPLE_PMGR_AUTO_ENABLE;
+               regmap_write(ps->regmap, ps->offset, reg);
+       }
+
+       return ret;
+}
+
+static bool apple_pmgr_ps_is_active(struct apple_pmgr_ps *ps)
+{
+       u32 reg = 0;
+
+       regmap_read(ps->regmap, ps->offset, &reg);
+       /*
+        * We consider domains as active if they are actually on, or if they have auto-PM
+        * enabled and the intended target is on.
+        */
+       return (FIELD_GET(APPLE_PMGR_PS_ACTUAL, reg) == APPLE_PMGR_PS_ACTIVE ||
+               (FIELD_GET(APPLE_PMGR_PS_TARGET, reg) == APPLE_PMGR_PS_ACTIVE &&
+                reg & APPLE_PMGR_AUTO_ENABLE));
+}
+
+static int apple_pmgr_ps_power_on(struct generic_pm_domain *genpd)
+{
+       return apple_pmgr_ps_set(genpd, APPLE_PMGR_PS_ACTIVE, true);
+}
+
+static int apple_pmgr_ps_power_off(struct generic_pm_domain *genpd)
+{
+       return apple_pmgr_ps_set(genpd, APPLE_PMGR_PS_PWRGATE, false);
+}
+
+static int apple_pmgr_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+       struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&ps->genpd.slock, flags);
+
+       if (ps->genpd.status == GENPD_STATE_OFF)
+               dev_err(ps->dev, "PS 0x%x: asserting RESET while powered down\n", ps->offset);
+
+       dev_dbg(ps->dev, "PS 0x%x: assert reset\n", ps->offset);
+       /* Quiesce device before asserting reset */
+       regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_DEV_DISABLE,
+                          APPLE_PMGR_DEV_DISABLE);
+       regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_RESET,
+                          APPLE_PMGR_RESET);
+
+       spin_unlock_irqrestore(&ps->genpd.slock, flags);
+
+       return 0;
+}
+
+static int apple_pmgr_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+       struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&ps->genpd.slock, flags);
+
+       dev_dbg(ps->dev, "PS 0x%x: deassert reset\n", ps->offset);
+       regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_RESET, 0);
+       regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_DEV_DISABLE, 0);
+
+       if (ps->genpd.status == GENPD_STATE_OFF)
+               dev_err(ps->dev, "PS 0x%x: RESET was deasserted while powered down\n", ps->offset);
+
+       spin_unlock_irqrestore(&ps->genpd.slock, flags);
+
+       return 0;
+}
+
+static int apple_pmgr_reset_reset(struct reset_controller_dev *rcdev, unsigned long id)
+{
+       int ret;
+
+       ret = apple_pmgr_reset_assert(rcdev, id);
+       if (ret)
+               return ret;
+
+       usleep_range(APPLE_PMGR_RESET_TIME, 2 * APPLE_PMGR_RESET_TIME);
+
+       return apple_pmgr_reset_deassert(rcdev, id);
+}
+
+static int apple_pmgr_reset_status(struct reset_controller_dev *rcdev, unsigned long id)
+{
+       struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev);
+       u32 reg = 0;
+
+       regmap_read(ps->regmap, ps->offset, &reg);
+
+       return !!(reg & APPLE_PMGR_RESET);
+}
+
+const struct reset_control_ops apple_pmgr_reset_ops = {
+       .assert         = apple_pmgr_reset_assert,
+       .deassert       = apple_pmgr_reset_deassert,
+       .reset          = apple_pmgr_reset_reset,
+       .status         = apple_pmgr_reset_status,
+};
+
+static int apple_pmgr_reset_xlate(struct reset_controller_dev *rcdev,
+                                 const struct of_phandle_args *reset_spec)
+{
+       return 0;
+}
+
+static int apple_pmgr_ps_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *node = dev->of_node;
+       struct apple_pmgr_ps *ps;
+       struct regmap *regmap;
+       struct of_phandle_iterator it;
+       int ret;
+       const char *name;
+       bool active;
+
+       regmap = syscon_node_to_regmap(node->parent);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
+       ps = devm_kzalloc(dev, sizeof(*ps), GFP_KERNEL);
+       if (!ps)
+               return -ENOMEM;
+
+       ps->dev = dev;
+       ps->regmap = regmap;
+
+       ret = of_property_read_string(node, "label", &name);
+       if (ret < 0) {
+               dev_err(dev, "missing label property\n");
+               return ret;
+       }
+
+       ret = of_property_read_u32(node, "reg", &ps->offset);
+       if (ret < 0) {
+               dev_err(dev, "missing reg property\n");
+               return ret;
+       }
+
+       ps->genpd.flags |= GENPD_FLAG_IRQ_SAFE;
+       ps->genpd.name = name;
+       ps->genpd.power_on = apple_pmgr_ps_power_on;
+       ps->genpd.power_off = apple_pmgr_ps_power_off;
+
+       ret = of_property_read_u32(node, "apple,min-state", &ps->min_state);
+       if (ret == 0 && ps->min_state <= APPLE_PMGR_PS_ACTIVE)
+               regmap_update_bits(regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_PS_MIN,
+                                  FIELD_PREP(APPLE_PMGR_PS_MIN, ps->min_state));
+
+       active = apple_pmgr_ps_is_active(ps);
+       if (of_property_read_bool(node, "apple,always-on")) {
+               ps->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
+               if (!active) {
+                       dev_warn(dev, "always-on domain %s is not on at boot\n", name);
+                       /* Turn it on so pm_genpd_init does not fail */
+                       active = apple_pmgr_ps_power_on(&ps->genpd) == 0;
+               }
+       }
+
+       /* Turn on auto-PM if the domain is already on */
+       if (active)
+               regmap_update_bits(regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_AUTO_ENABLE,
+                                  APPLE_PMGR_AUTO_ENABLE);
+
+       ret = pm_genpd_init(&ps->genpd, NULL, !active);
+       if (ret < 0) {
+               dev_err(dev, "pm_genpd_init failed\n");
+               return ret;
+       }
+
+       ret = of_genpd_add_provider_simple(node, &ps->genpd);
+       if (ret < 0) {
+               dev_err(dev, "of_genpd_add_provider_simple failed\n");
+               return ret;
+       }
+
+       of_for_each_phandle(&it, ret, node, "power-domains", "#power-domain-cells", -1) {
+               struct of_phandle_args parent, child;
+
+               parent.np = it.node;
+               parent.args_count = of_phandle_iterator_args(&it, parent.args, MAX_PHANDLE_ARGS);
+               child.np = node;
+               child.args_count = 0;
+               ret = of_genpd_add_subdomain(&parent, &child);
+
+               if (ret == -EPROBE_DEFER) {
+                       of_node_put(parent.np);
+                       goto err_remove;
+               } else if (ret < 0) {
+                       dev_err(dev, "failed to add to parent domain: %d (%s -> %s)\n",
+                               ret, it.node->name, node->name);
+                       of_node_put(parent.np);
+                       goto err_remove;
+               }
+       }
+
+       /*
+        * Do not participate in regular PM; parent power domains are handled via the
+        * genpd hierarchy.
+        */
+       pm_genpd_remove_device(dev);
+
+       ps->rcdev.owner = THIS_MODULE;
+       ps->rcdev.nr_resets = 1;
+       ps->rcdev.ops = &apple_pmgr_reset_ops;
+       ps->rcdev.of_node = dev->of_node;
+       ps->rcdev.of_reset_n_cells = 0;
+       ps->rcdev.of_xlate = apple_pmgr_reset_xlate;
+
+       ret = devm_reset_controller_register(dev, &ps->rcdev);
+       if (ret < 0)
+               goto err_remove;
+
+       return 0;
+err_remove:
+       of_genpd_del_provider(node);
+       pm_genpd_remove(&ps->genpd);
+       return ret;
+}
+
+static const struct of_device_id apple_pmgr_ps_of_match[] = {
+       { .compatible = "apple,pmgr-pwrstate" },
+       {}
+};
+
+MODULE_DEVICE_TABLE(of, apple_pmgr_ps_of_match);
+
+static struct platform_driver apple_pmgr_ps_driver = {
+       .probe = apple_pmgr_ps_probe,
+       .driver = {
+               .name = "apple-pmgr-pwrstate",
+               .of_match_table = apple_pmgr_ps_of_match,
+       },
+};
+
+MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
+MODULE_DESCRIPTION("PMGR power state driver for Apple SoCs");
+
+module_platform_driver(apple_pmgr_ps_driver);
diff --git a/drivers/pmdomain/bcm/Makefile b/drivers/pmdomain/bcm/Makefile
new file mode 100644 (file)
index 0000000..6bfbe4e
--- /dev/null
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_BCM_PMB)                  += bcm-pmb.o
+obj-$(CONFIG_BCM2835_POWER)            += bcm2835-power.o
+obj-$(CONFIG_BCM63XX_POWER)            += bcm63xx-power.o
+obj-$(CONFIG_RASPBERRYPI_POWER)                += raspberrypi-power.o
diff --git a/drivers/pmdomain/bcm/bcm-pmb.c b/drivers/pmdomain/bcm/bcm-pmb.c
new file mode 100644 (file)
index 0000000..a72ba26
--- /dev/null
@@ -0,0 +1,363 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2013 Broadcom
+ * Copyright (C) 2020 Rafał Miłecki <rafal@milecki.pl>
+ */
+
+#include <dt-bindings/soc/bcm-pmb.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/reset/bcm63xx_pmb.h>
+
+#define BPCM_ID_REG                                    0x00
+#define BPCM_CAPABILITIES                              0x04
+#define  BPCM_CAP_NUM_ZONES                            0x000000ff
+#define  BPCM_CAP_SR_REG_BITS                          0x0000ff00
+#define  BPCM_CAP_PLLTYPE                              0x00030000
+#define  BPCM_CAP_UBUS                                 0x00080000
+#define BPCM_CONTROL                                   0x08
+#define BPCM_STATUS                                    0x0c
+#define BPCM_ROSC_CONTROL                              0x10
+#define BPCM_ROSC_THRESH_H                             0x14
+#define BPCM_ROSC_THRESHOLD_BCM6838                    0x14
+#define BPCM_ROSC_THRESH_S                             0x18
+#define BPCM_ROSC_COUNT_BCM6838                                0x18
+#define BPCM_ROSC_COUNT                                        0x1c
+#define BPCM_PWD_CONTROL_BCM6838                       0x1c
+#define BPCM_PWD_CONTROL                               0x20
+#define BPCM_SR_CONTROL_BCM6838                                0x20
+#define BPCM_PWD_ACCUM_CONTROL                         0x24
+#define BPCM_SR_CONTROL                                        0x28
+#define BPCM_GLOBAL_CONTROL                            0x2c
+#define BPCM_MISC_CONTROL                              0x30
+#define BPCM_MISC_CONTROL2                             0x34
+#define BPCM_SGPHY_CNTL                                        0x38
+#define BPCM_SGPHY_STATUS                              0x3c
+#define BPCM_ZONE0                                     0x40
+#define  BPCM_ZONE_CONTROL                             0x00
+#define   BPCM_ZONE_CONTROL_MANUAL_CLK_EN              0x00000001
+#define   BPCM_ZONE_CONTROL_MANUAL_RESET_CTL           0x00000002
+#define   BPCM_ZONE_CONTROL_FREQ_SCALE_USED            0x00000004      /* R/O */
+#define   BPCM_ZONE_CONTROL_DPG_CAPABLE                        0x00000008      /* R/O */
+#define   BPCM_ZONE_CONTROL_MANUAL_MEM_PWR             0x00000030
+#define   BPCM_ZONE_CONTROL_MANUAL_ISO_CTL             0x00000040
+#define   BPCM_ZONE_CONTROL_MANUAL_CTL                 0x00000080
+#define   BPCM_ZONE_CONTROL_DPG_CTL_EN                 0x00000100
+#define   BPCM_ZONE_CONTROL_PWR_DN_REQ                 0x00000200
+#define   BPCM_ZONE_CONTROL_PWR_UP_REQ                 0x00000400
+#define   BPCM_ZONE_CONTROL_MEM_PWR_CTL_EN             0x00000800
+#define   BPCM_ZONE_CONTROL_BLK_RESET_ASSERT           0x00001000
+#define   BPCM_ZONE_CONTROL_MEM_STBY                   0x00002000
+#define   BPCM_ZONE_CONTROL_RESERVED                   0x0007c000
+#define   BPCM_ZONE_CONTROL_PWR_CNTL_STATE             0x00f80000
+#define   BPCM_ZONE_CONTROL_FREQ_SCALAR_DYN_SEL                0x01000000      /* R/O */
+#define   BPCM_ZONE_CONTROL_PWR_OFF_STATE              0x02000000      /* R/O */
+#define   BPCM_ZONE_CONTROL_PWR_ON_STATE               0x04000000      /* R/O */
+#define   BPCM_ZONE_CONTROL_PWR_GOOD                   0x08000000      /* R/O */
+#define   BPCM_ZONE_CONTROL_DPG_PWR_STATE              0x10000000      /* R/O */
+#define   BPCM_ZONE_CONTROL_MEM_PWR_STATE              0x20000000      /* R/O */
+#define   BPCM_ZONE_CONTROL_ISO_STATE                  0x40000000      /* R/O */
+#define   BPCM_ZONE_CONTROL_RESET_STATE                        0x80000000      /* R/O */
+#define  BPCM_ZONE_CONFIG1                             0x04
+#define  BPCM_ZONE_CONFIG2                             0x08
+#define  BPCM_ZONE_FREQ_SCALAR_CONTROL                 0x0c
+#define  BPCM_ZONE_SIZE                                        0x10
+
+struct bcm_pmb {
+       struct device *dev;
+       void __iomem *base;
+       spinlock_t lock;
+       bool little_endian;
+       struct genpd_onecell_data genpd_onecell_data;
+};
+
+struct bcm_pmb_pd_data {
+       const char * const name;
+       int id;
+       u8 bus;
+       u8 device;
+};
+
+struct bcm_pmb_pm_domain {
+       struct bcm_pmb *pmb;
+       const struct bcm_pmb_pd_data *data;
+       struct generic_pm_domain genpd;
+};
+
+static int bcm_pmb_bpcm_read(struct bcm_pmb *pmb, int bus, u8 device,
+                            int offset, u32 *val)
+{
+       void __iomem *base = pmb->base + bus * 0x20;
+       unsigned long flags;
+       int err;
+
+       spin_lock_irqsave(&pmb->lock, flags);
+       err = bpcm_rd(base, device, offset, val);
+       spin_unlock_irqrestore(&pmb->lock, flags);
+
+       if (!err)
+               *val = pmb->little_endian ? le32_to_cpu(*val) : be32_to_cpu(*val);
+
+       return err;
+}
+
+static int bcm_pmb_bpcm_write(struct bcm_pmb *pmb, int bus, u8 device,
+                             int offset, u32 val)
+{
+       void __iomem *base = pmb->base + bus * 0x20;
+       unsigned long flags;
+       int err;
+
+       val = pmb->little_endian ? cpu_to_le32(val) : cpu_to_be32(val);
+
+       spin_lock_irqsave(&pmb->lock, flags);
+       err = bpcm_wr(base, device, offset, val);
+       spin_unlock_irqrestore(&pmb->lock, flags);
+
+       return err;
+}
+
+static int bcm_pmb_power_off_zone(struct bcm_pmb *pmb, int bus, u8 device,
+                                 int zone)
+{
+       int offset;
+       u32 val;
+       int err;
+
+       offset = BPCM_ZONE0 + zone * BPCM_ZONE_SIZE + BPCM_ZONE_CONTROL;
+
+       err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val);
+       if (err)
+               return err;
+
+       val |= BPCM_ZONE_CONTROL_PWR_DN_REQ;
+       val &= ~BPCM_ZONE_CONTROL_PWR_UP_REQ;
+
+       err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val);
+
+       return err;
+}
+
+static int bcm_pmb_power_on_zone(struct bcm_pmb *pmb, int bus, u8 device,
+                                int zone)
+{
+       int offset;
+       u32 val;
+       int err;
+
+       offset = BPCM_ZONE0 + zone * BPCM_ZONE_SIZE + BPCM_ZONE_CONTROL;
+
+       err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val);
+       if (err)
+               return err;
+
+       if (!(val & BPCM_ZONE_CONTROL_PWR_ON_STATE)) {
+               val &= ~BPCM_ZONE_CONTROL_PWR_DN_REQ;
+               val |= BPCM_ZONE_CONTROL_DPG_CTL_EN;
+               val |= BPCM_ZONE_CONTROL_PWR_UP_REQ;
+               val |= BPCM_ZONE_CONTROL_MEM_PWR_CTL_EN;
+               val |= BPCM_ZONE_CONTROL_BLK_RESET_ASSERT;
+
+               err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val);
+       }
+
+       return err;
+}
+
+static int bcm_pmb_power_off_device(struct bcm_pmb *pmb, int bus, u8 device)
+{
+       int offset;
+       u32 val;
+       int err;
+
+       /* Entire device can be powered off by powering off the 0th zone */
+       offset = BPCM_ZONE0 + BPCM_ZONE_CONTROL;
+
+       err = bcm_pmb_bpcm_read(pmb, bus, device, offset, &val);
+       if (err)
+               return err;
+
+       if (!(val & BPCM_ZONE_CONTROL_PWR_OFF_STATE)) {
+               val = BPCM_ZONE_CONTROL_PWR_DN_REQ;
+
+               err = bcm_pmb_bpcm_write(pmb, bus, device, offset, val);
+       }
+
+       return err;
+}
+
+static int bcm_pmb_power_on_device(struct bcm_pmb *pmb, int bus, u8 device)
+{
+       u32 val;
+       int err;
+       int i;
+
+       err = bcm_pmb_bpcm_read(pmb, bus, device, BPCM_CAPABILITIES, &val);
+       if (err)
+               return err;
+
+       for (i = 0; i < (val & BPCM_CAP_NUM_ZONES); i++) {
+               err = bcm_pmb_power_on_zone(pmb, bus, device, i);
+               if (err)
+                       return err;
+       }
+
+       return err;
+}
+
+static int bcm_pmb_power_on_sata(struct bcm_pmb *pmb, int bus, u8 device)
+{
+       int err;
+
+       err = bcm_pmb_power_on_zone(pmb, bus, device, 0);
+       if (err)
+               return err;
+
+       /* Does not apply to the BCM963158 */
+       err = bcm_pmb_bpcm_write(pmb, bus, device, BPCM_MISC_CONTROL, 0);
+       if (err)
+               return err;
+
+       err = bcm_pmb_bpcm_write(pmb, bus, device, BPCM_SR_CONTROL, 0xffffffff);
+       if (err)
+               return err;
+
+       err = bcm_pmb_bpcm_write(pmb, bus, device, BPCM_SR_CONTROL, 0);
+
+       return err;
+}
+
+static int bcm_pmb_power_on(struct generic_pm_domain *genpd)
+{
+       struct bcm_pmb_pm_domain *pd = container_of(genpd, struct bcm_pmb_pm_domain, genpd);
+       const struct bcm_pmb_pd_data *data = pd->data;
+       struct bcm_pmb *pmb = pd->pmb;
+
+       switch (data->id) {
+       case BCM_PMB_PCIE0:
+       case BCM_PMB_PCIE1:
+       case BCM_PMB_PCIE2:
+               return bcm_pmb_power_on_zone(pmb, data->bus, data->device, 0);
+       case BCM_PMB_HOST_USB:
+               return bcm_pmb_power_on_device(pmb, data->bus, data->device);
+       case BCM_PMB_SATA:
+               return bcm_pmb_power_on_sata(pmb, data->bus, data->device);
+       default:
+               dev_err(pmb->dev, "unsupported device id: %d\n", data->id);
+               return -EINVAL;
+       }
+}
+
+static int bcm_pmb_power_off(struct generic_pm_domain *genpd)
+{
+       struct bcm_pmb_pm_domain *pd = container_of(genpd, struct bcm_pmb_pm_domain, genpd);
+       const struct bcm_pmb_pd_data *data = pd->data;
+       struct bcm_pmb *pmb = pd->pmb;
+
+       switch (data->id) {
+       case BCM_PMB_PCIE0:
+       case BCM_PMB_PCIE1:
+       case BCM_PMB_PCIE2:
+               return bcm_pmb_power_off_zone(pmb, data->bus, data->device, 0);
+       case BCM_PMB_HOST_USB:
+               return bcm_pmb_power_off_device(pmb, data->bus, data->device);
+       default:
+               dev_err(pmb->dev, "unsupported device id: %d\n", data->id);
+               return -EINVAL;
+       }
+}
+
+static int bcm_pmb_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       const struct bcm_pmb_pd_data *table;
+       const struct bcm_pmb_pd_data *e;
+       struct bcm_pmb *pmb;
+       int max_id;
+       int err;
+
+       pmb = devm_kzalloc(dev, sizeof(*pmb), GFP_KERNEL);
+       if (!pmb)
+               return -ENOMEM;
+
+       pmb->dev = dev;
+
+       pmb->base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(pmb->base))
+               return PTR_ERR(pmb->base);
+
+       spin_lock_init(&pmb->lock);
+
+       pmb->little_endian = !of_device_is_big_endian(dev->of_node);
+
+       table = of_device_get_match_data(dev);
+       if (!table)
+               return -EINVAL;
+
+       max_id = 0;
+       for (e = table; e->name; e++)
+               max_id = max(max_id, e->id);
+
+       pmb->genpd_onecell_data.num_domains = max_id + 1;
+       pmb->genpd_onecell_data.domains =
+               devm_kcalloc(dev, pmb->genpd_onecell_data.num_domains,
+                            sizeof(struct generic_pm_domain *), GFP_KERNEL);
+       if (!pmb->genpd_onecell_data.domains)
+               return -ENOMEM;
+
+       for (e = table; e->name; e++) {
+               struct bcm_pmb_pm_domain *pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+
+               if (!pd)
+                       return -ENOMEM;
+
+               pd->pmb = pmb;
+               pd->data = e;
+               pd->genpd.name = e->name;
+               pd->genpd.power_on = bcm_pmb_power_on;
+               pd->genpd.power_off = bcm_pmb_power_off;
+
+               pm_genpd_init(&pd->genpd, NULL, true);
+               pmb->genpd_onecell_data.domains[e->id] = &pd->genpd;
+       }
+
+       err = of_genpd_add_provider_onecell(dev->of_node, &pmb->genpd_onecell_data);
+       if (err) {
+               dev_err(dev, "failed to add genpd provider: %d\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+static const struct bcm_pmb_pd_data bcm_pmb_bcm4908_data[] = {
+       { .name = "pcie2", .id = BCM_PMB_PCIE2, .bus = 0, .device = 2, },
+       { .name = "pcie0", .id = BCM_PMB_PCIE0, .bus = 1, .device = 14, },
+       { .name = "pcie1", .id = BCM_PMB_PCIE1, .bus = 1, .device = 15, },
+       { .name = "usb", .id = BCM_PMB_HOST_USB, .bus = 1, .device = 17, },
+       { },
+};
+
+static const struct bcm_pmb_pd_data bcm_pmb_bcm63138_data[] = {
+       { .name = "sata", .id = BCM_PMB_SATA, .bus = 0, .device = 3, },
+       { },
+};
+
+static const struct of_device_id bcm_pmb_of_match[] = {
+       { .compatible = "brcm,bcm4908-pmb", .data = &bcm_pmb_bcm4908_data, },
+       { .compatible = "brcm,bcm63138-pmb", .data = &bcm_pmb_bcm63138_data, },
+       { },
+};
+
+static struct platform_driver bcm_pmb_driver = {
+       .driver = {
+               .name = "bcm-pmb",
+               .of_match_table = bcm_pmb_of_match,
+       },
+       .probe  = bcm_pmb_probe,
+};
+
+builtin_platform_driver(bcm_pmb_driver);
diff --git a/drivers/pmdomain/bcm/bcm2835-power.c b/drivers/pmdomain/bcm/bcm2835-power.c
new file mode 100644 (file)
index 0000000..1a179d4
--- /dev/null
@@ -0,0 +1,713 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Power domain driver for Broadcom BCM2835
+ *
+ * Copyright (C) 2018 Broadcom
+ */
+
+#include <dt-bindings/soc/bcm2835-pm.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/bcm2835-pm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/reset-controller.h>
+#include <linux/types.h>
+
+#define PM_GNRIC                        0x00
+#define PM_AUDIO                        0x04
+#define PM_STATUS                       0x18
+#define PM_RSTC                                0x1c
+#define PM_RSTS                                0x20
+#define PM_WDOG                                0x24
+#define PM_PADS0                       0x28
+#define PM_PADS2                       0x2c
+#define PM_PADS3                       0x30
+#define PM_PADS4                       0x34
+#define PM_PADS5                       0x38
+#define PM_PADS6                       0x3c
+#define PM_CAM0                                0x44
+#define PM_CAM0_LDOHPEN                        BIT(2)
+#define PM_CAM0_LDOLPEN                        BIT(1)
+#define PM_CAM0_CTRLEN                 BIT(0)
+
+#define PM_CAM1                                0x48
+#define PM_CAM1_LDOHPEN                        BIT(2)
+#define PM_CAM1_LDOLPEN                        BIT(1)
+#define PM_CAM1_CTRLEN                 BIT(0)
+
+#define PM_CCP2TX                      0x4c
+#define PM_CCP2TX_LDOEN                        BIT(1)
+#define PM_CCP2TX_CTRLEN               BIT(0)
+
+#define PM_DSI0                                0x50
+#define PM_DSI0_LDOHPEN                        BIT(2)
+#define PM_DSI0_LDOLPEN                        BIT(1)
+#define PM_DSI0_CTRLEN                 BIT(0)
+
+#define PM_DSI1                                0x54
+#define PM_DSI1_LDOHPEN                        BIT(2)
+#define PM_DSI1_LDOLPEN                        BIT(1)
+#define PM_DSI1_CTRLEN                 BIT(0)
+
+#define PM_HDMI                                0x58
+#define PM_HDMI_RSTDR                  BIT(19)
+#define PM_HDMI_LDOPD                  BIT(1)
+#define PM_HDMI_CTRLEN                 BIT(0)
+
+#define PM_USB                         0x5c
+/* The power gates must be enabled with this bit before enabling the LDO in the
+ * USB block.
+ */
+#define PM_USB_CTRLEN                  BIT(0)
+
+#define PM_PXLDO                       0x60
+#define PM_PXBG                                0x64
+#define PM_DFT                         0x68
+#define PM_SMPS                                0x6c
+#define PM_XOSC                                0x70
+#define PM_SPAREW                      0x74
+#define PM_SPARER                      0x78
+#define PM_AVS_RSTDR                   0x7c
+#define PM_AVS_STAT                    0x80
+#define PM_AVS_EVENT                   0x84
+#define PM_AVS_INTEN                   0x88
+#define PM_DUMMY                       0xfc
+
+#define PM_IMAGE                       0x108
+#define PM_GRAFX                       0x10c
+#define PM_PROC                                0x110
+#define PM_ENAB                                BIT(12)
+#define PM_ISPRSTN                     BIT(8)
+#define PM_H264RSTN                    BIT(7)
+#define PM_PERIRSTN                    BIT(6)
+#define PM_V3DRSTN                     BIT(6)
+#define PM_ISFUNC                      BIT(5)
+#define PM_MRDONE                      BIT(4)
+#define PM_MEMREP                      BIT(3)
+#define PM_ISPOW                       BIT(2)
+#define PM_POWOK                       BIT(1)
+#define PM_POWUP                       BIT(0)
+#define PM_INRUSH_SHIFT                        13
+#define PM_INRUSH_3_5_MA               0
+#define PM_INRUSH_5_MA                 1
+#define PM_INRUSH_10_MA                        2
+#define PM_INRUSH_20_MA                        3
+#define PM_INRUSH_MASK                 (3 << PM_INRUSH_SHIFT)
+
+#define PM_PASSWORD                    0x5a000000
+
+#define PM_WDOG_TIME_SET               0x000fffff
+#define PM_RSTC_WRCFG_CLR              0xffffffcf
+#define PM_RSTS_HADWRH_SET             0x00000040
+#define PM_RSTC_WRCFG_SET              0x00000030
+#define PM_RSTC_WRCFG_FULL_RESET       0x00000020
+#define PM_RSTC_RESET                  0x00000102
+
+#define PM_READ(reg) readl(power->base + (reg))
+#define PM_WRITE(reg, val) writel(PM_PASSWORD | (val), power->base + (reg))
+
+#define ASB_BRDG_VERSION                0x00
+#define ASB_CPR_CTRL                    0x04
+
+#define ASB_V3D_S_CTRL                 0x08
+#define ASB_V3D_M_CTRL                 0x0c
+#define ASB_ISP_S_CTRL                 0x10
+#define ASB_ISP_M_CTRL                 0x14
+#define ASB_H264_S_CTRL                        0x18
+#define ASB_H264_M_CTRL                        0x1c
+
+#define ASB_REQ_STOP                    BIT(0)
+#define ASB_ACK                         BIT(1)
+#define ASB_EMPTY                       BIT(2)
+#define ASB_FULL                        BIT(3)
+
+#define ASB_AXI_BRDG_ID                        0x20
+
+#define BCM2835_BRDG_ID                        0x62726467
+
+struct bcm2835_power_domain {
+       struct generic_pm_domain base;
+       struct bcm2835_power *power;
+       u32 domain;
+       struct clk *clk;
+};
+
+struct bcm2835_power {
+       struct device           *dev;
+       /* PM registers. */
+       void __iomem            *base;
+       /* AXI Async bridge registers. */
+       void __iomem            *asb;
+       /* RPiVid bridge registers. */
+       void __iomem            *rpivid_asb;
+
+       struct genpd_onecell_data pd_xlate;
+       struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
+       struct reset_controller_dev reset;
+};
+
+static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable)
+{
+       void __iomem *base = power->asb;
+       u64 start;
+       u32 val;
+
+       switch (reg) {
+       case 0:
+               return 0;
+       case ASB_V3D_S_CTRL:
+       case ASB_V3D_M_CTRL:
+               if (power->rpivid_asb)
+                       base = power->rpivid_asb;
+               break;
+       }
+
+       start = ktime_get_ns();
+
+       /* Enable the module's async AXI bridges. */
+       if (enable) {
+               val = readl(base + reg) & ~ASB_REQ_STOP;
+       } else {
+               val = readl(base + reg) | ASB_REQ_STOP;
+       }
+       writel(PM_PASSWORD | val, base + reg);
+
+       while (readl(base + reg) & ASB_ACK) {
+               cpu_relax();
+               if (ktime_get_ns() - start >= 1000)
+                       return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int bcm2835_asb_enable(struct bcm2835_power *power, u32 reg)
+{
+       return bcm2835_asb_control(power, reg, true);
+}
+
+static int bcm2835_asb_disable(struct bcm2835_power *power, u32 reg)
+{
+       return bcm2835_asb_control(power, reg, false);
+}
+
+static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg)
+{
+       struct bcm2835_power *power = pd->power;
+
+       /* We don't run this on BCM2711 */
+       if (power->rpivid_asb)
+               return 0;
+
+       /* Enable functional isolation */
+       PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
+
+       /* Enable electrical isolation */
+       PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
+
+       /* Open the power switches. */
+       PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_POWUP);
+
+       return 0;
+}
+
+static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg)
+{
+       struct bcm2835_power *power = pd->power;
+       struct device *dev = power->dev;
+       u64 start;
+       int ret;
+       int inrush;
+       bool powok;
+
+       /* We don't run this on BCM2711 */
+       if (power->rpivid_asb)
+               return 0;
+
+       /* If it was already powered on by the fw, leave it that way. */
+       if (PM_READ(pm_reg) & PM_POWUP)
+               return 0;
+
+       /* Enable power.  Allowing too much current at once may result
+        * in POWOK never getting set, so start low and ramp it up as
+        * necessary to succeed.
+        */
+       powok = false;
+       for (inrush = PM_INRUSH_3_5_MA; inrush <= PM_INRUSH_20_MA; inrush++) {
+               PM_WRITE(pm_reg,
+                        (PM_READ(pm_reg) & ~PM_INRUSH_MASK) |
+                        (inrush << PM_INRUSH_SHIFT) |
+                        PM_POWUP);
+
+               start = ktime_get_ns();
+               while (!(powok = !!(PM_READ(pm_reg) & PM_POWOK))) {
+                       cpu_relax();
+                       if (ktime_get_ns() - start >= 3000)
+                               break;
+               }
+       }
+       if (!powok) {
+               dev_err(dev, "Timeout waiting for %s power OK\n",
+                       pd->base.name);
+               ret = -ETIMEDOUT;
+               goto err_disable_powup;
+       }
+
+       /* Disable electrical isolation */
+       PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISPOW);
+
+       /* Repair memory */
+       PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_MEMREP);
+       start = ktime_get_ns();
+       while (!(PM_READ(pm_reg) & PM_MRDONE)) {
+               cpu_relax();
+               if (ktime_get_ns() - start >= 1000) {
+                       dev_err(dev, "Timeout waiting for %s memory repair\n",
+                               pd->base.name);
+                       ret = -ETIMEDOUT;
+                       goto err_disable_ispow;
+               }
+       }
+
+       /* Disable functional isolation */
+       PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISFUNC);
+
+       return 0;
+
+err_disable_ispow:
+       PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
+err_disable_powup:
+       PM_WRITE(pm_reg, PM_READ(pm_reg) & ~(PM_POWUP | PM_INRUSH_MASK));
+       return ret;
+}
+
+static int bcm2835_asb_power_on(struct bcm2835_power_domain *pd,
+                               u32 pm_reg,
+                               u32 asb_m_reg,
+                               u32 asb_s_reg,
+                               u32 reset_flags)
+{
+       struct bcm2835_power *power = pd->power;
+       int ret;
+
+       ret = clk_prepare_enable(pd->clk);
+       if (ret) {
+               dev_err(power->dev, "Failed to enable clock for %s\n",
+                       pd->base.name);
+               return ret;
+       }
+
+       /* Wait 32 clocks for reset to propagate, 1 us will be enough */
+       udelay(1);
+
+       clk_disable_unprepare(pd->clk);
+
+       /* Deassert the resets. */
+       PM_WRITE(pm_reg, PM_READ(pm_reg) | reset_flags);
+
+       ret = clk_prepare_enable(pd->clk);
+       if (ret) {
+               dev_err(power->dev, "Failed to enable clock for %s\n",
+                       pd->base.name);
+               goto err_enable_resets;
+       }
+
+       ret = bcm2835_asb_enable(power, asb_m_reg);
+       if (ret) {
+               dev_err(power->dev, "Failed to enable ASB master for %s\n",
+                       pd->base.name);
+               goto err_disable_clk;
+       }
+       ret = bcm2835_asb_enable(power, asb_s_reg);
+       if (ret) {
+               dev_err(power->dev, "Failed to enable ASB slave for %s\n",
+                       pd->base.name);
+               goto err_disable_asb_master;
+       }
+
+       return 0;
+
+err_disable_asb_master:
+       bcm2835_asb_disable(power, asb_m_reg);
+err_disable_clk:
+       clk_disable_unprepare(pd->clk);
+err_enable_resets:
+       PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
+       return ret;
+}
+
+static int bcm2835_asb_power_off(struct bcm2835_power_domain *pd,
+                                u32 pm_reg,
+                                u32 asb_m_reg,
+                                u32 asb_s_reg,
+                                u32 reset_flags)
+{
+       struct bcm2835_power *power = pd->power;
+       int ret;
+
+       ret = bcm2835_asb_disable(power, asb_s_reg);
+       if (ret) {
+               dev_warn(power->dev, "Failed to disable ASB slave for %s\n",
+                        pd->base.name);
+               return ret;
+       }
+       ret = bcm2835_asb_disable(power, asb_m_reg);
+       if (ret) {
+               dev_warn(power->dev, "Failed to disable ASB master for %s\n",
+                        pd->base.name);
+               bcm2835_asb_enable(power, asb_s_reg);
+               return ret;
+       }
+
+       clk_disable_unprepare(pd->clk);
+
+       /* Assert the resets. */
+       PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
+
+       return 0;
+}
+
+static int bcm2835_power_pd_power_on(struct generic_pm_domain *domain)
+{
+       struct bcm2835_power_domain *pd =
+               container_of(domain, struct bcm2835_power_domain, base);
+       struct bcm2835_power *power = pd->power;
+
+       switch (pd->domain) {
+       case BCM2835_POWER_DOMAIN_GRAFX:
+               return bcm2835_power_power_on(pd, PM_GRAFX);
+
+       case BCM2835_POWER_DOMAIN_GRAFX_V3D:
+               return bcm2835_asb_power_on(pd, PM_GRAFX,
+                                           ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
+                                           PM_V3DRSTN);
+
+       case BCM2835_POWER_DOMAIN_IMAGE:
+               return bcm2835_power_power_on(pd, PM_IMAGE);
+
+       case BCM2835_POWER_DOMAIN_IMAGE_PERI:
+               return bcm2835_asb_power_on(pd, PM_IMAGE,
+                                           0, 0,
+                                           PM_PERIRSTN);
+
+       case BCM2835_POWER_DOMAIN_IMAGE_ISP:
+               return bcm2835_asb_power_on(pd, PM_IMAGE,
+                                           ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
+                                           PM_ISPRSTN);
+
+       case BCM2835_POWER_DOMAIN_IMAGE_H264:
+               return bcm2835_asb_power_on(pd, PM_IMAGE,
+                                           ASB_H264_M_CTRL, ASB_H264_S_CTRL,
+                                           PM_H264RSTN);
+
+       case BCM2835_POWER_DOMAIN_USB:
+               PM_WRITE(PM_USB, PM_USB_CTRLEN);
+               return 0;
+
+       case BCM2835_POWER_DOMAIN_DSI0:
+               PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
+               PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN | PM_DSI0_LDOHPEN);
+               return 0;
+
+       case BCM2835_POWER_DOMAIN_DSI1:
+               PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
+               PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN | PM_DSI1_LDOHPEN);
+               return 0;
+
+       case BCM2835_POWER_DOMAIN_CCP2TX:
+               PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
+               PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN | PM_CCP2TX_LDOEN);
+               return 0;
+
+       case BCM2835_POWER_DOMAIN_HDMI:
+               PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_RSTDR);
+               PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_CTRLEN);
+               PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_LDOPD);
+               usleep_range(100, 200);
+               PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_RSTDR);
+               return 0;
+
+       default:
+               dev_err(power->dev, "Invalid domain %d\n", pd->domain);
+               return -EINVAL;
+       }
+}
+
+static int bcm2835_power_pd_power_off(struct generic_pm_domain *domain)
+{
+       struct bcm2835_power_domain *pd =
+               container_of(domain, struct bcm2835_power_domain, base);
+       struct bcm2835_power *power = pd->power;
+
+       switch (pd->domain) {
+       case BCM2835_POWER_DOMAIN_GRAFX:
+               return bcm2835_power_power_off(pd, PM_GRAFX);
+
+       case BCM2835_POWER_DOMAIN_GRAFX_V3D:
+               return bcm2835_asb_power_off(pd, PM_GRAFX,
+                                            ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
+                                            PM_V3DRSTN);
+
+       case BCM2835_POWER_DOMAIN_IMAGE:
+               return bcm2835_power_power_off(pd, PM_IMAGE);
+
+       case BCM2835_POWER_DOMAIN_IMAGE_PERI:
+               return bcm2835_asb_power_off(pd, PM_IMAGE,
+                                            0, 0,
+                                            PM_PERIRSTN);
+
+       case BCM2835_POWER_DOMAIN_IMAGE_ISP:
+               return bcm2835_asb_power_off(pd, PM_IMAGE,
+                                            ASB_ISP_M_CTRL, ASB_ISP_S_CTRL,
+                                            PM_ISPRSTN);
+
+       case BCM2835_POWER_DOMAIN_IMAGE_H264:
+               return bcm2835_asb_power_off(pd, PM_IMAGE,
+                                            ASB_H264_M_CTRL, ASB_H264_S_CTRL,
+                                            PM_H264RSTN);
+
+       case BCM2835_POWER_DOMAIN_USB:
+               PM_WRITE(PM_USB, 0);
+               return 0;
+
+       case BCM2835_POWER_DOMAIN_DSI0:
+               PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
+               PM_WRITE(PM_DSI0, 0);
+               return 0;
+
+       case BCM2835_POWER_DOMAIN_DSI1:
+               PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
+               PM_WRITE(PM_DSI1, 0);
+               return 0;
+
+       case BCM2835_POWER_DOMAIN_CCP2TX:
+               PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
+               PM_WRITE(PM_CCP2TX, 0);
+               return 0;
+
+       case BCM2835_POWER_DOMAIN_HDMI:
+               PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_LDOPD);
+               PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_CTRLEN);
+               return 0;
+
+       default:
+               dev_err(power->dev, "Invalid domain %d\n", pd->domain);
+               return -EINVAL;
+       }
+}
+
+static int
+bcm2835_init_power_domain(struct bcm2835_power *power,
+                         int pd_xlate_index, const char *name)
+{
+       struct device *dev = power->dev;
+       struct bcm2835_power_domain *dom = &power->domains[pd_xlate_index];
+
+       dom->clk = devm_clk_get(dev->parent, name);
+       if (IS_ERR(dom->clk)) {
+               int ret = PTR_ERR(dom->clk);
+
+               if (ret == -EPROBE_DEFER)
+                       return ret;
+
+               /* Some domains don't have a clk, so make sure that we
+                * don't deref an error pointer later.
+                */
+               dom->clk = NULL;
+       }
+
+       dom->base.name = name;
+       dom->base.power_on = bcm2835_power_pd_power_on;
+       dom->base.power_off = bcm2835_power_pd_power_off;
+
+       dom->domain = pd_xlate_index;
+       dom->power = power;
+
+       /* XXX: on/off at boot? */
+       pm_genpd_init(&dom->base, NULL, true);
+
+       power->pd_xlate.domains[pd_xlate_index] = &dom->base;
+
+       return 0;
+}
+
+/** bcm2835_reset_reset - Resets a block that has a reset line in the
+ * PM block.
+ *
+ * The consumer of the reset controller must have the power domain up
+ * -- there's no reset ability with the power domain down.  To reset
+ * the sub-block, we just disable its access to memory through the
+ * ASB, reset, and re-enable.
+ */
+static int bcm2835_reset_reset(struct reset_controller_dev *rcdev,
+                              unsigned long id)
+{
+       struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
+                                                  reset);
+       struct bcm2835_power_domain *pd;
+       int ret;
+
+       switch (id) {
+       case BCM2835_RESET_V3D:
+               pd = &power->domains[BCM2835_POWER_DOMAIN_GRAFX_V3D];
+               break;
+       case BCM2835_RESET_H264:
+               pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_H264];
+               break;
+       case BCM2835_RESET_ISP:
+               pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_ISP];
+               break;
+       default:
+               dev_err(power->dev, "Bad reset id %ld\n", id);
+               return -EINVAL;
+       }
+
+       ret = bcm2835_power_pd_power_off(&pd->base);
+       if (ret)
+               return ret;
+
+       return bcm2835_power_pd_power_on(&pd->base);
+}
+
+static int bcm2835_reset_status(struct reset_controller_dev *rcdev,
+                               unsigned long id)
+{
+       struct bcm2835_power *power = container_of(rcdev, struct bcm2835_power,
+                                                  reset);
+
+       switch (id) {
+       case BCM2835_RESET_V3D:
+               return !PM_READ(PM_GRAFX & PM_V3DRSTN);
+       case BCM2835_RESET_H264:
+               return !PM_READ(PM_IMAGE & PM_H264RSTN);
+       case BCM2835_RESET_ISP:
+               return !PM_READ(PM_IMAGE & PM_ISPRSTN);
+       default:
+               return -EINVAL;
+       }
+}
+
+static const struct reset_control_ops bcm2835_reset_ops = {
+       .reset = bcm2835_reset_reset,
+       .status = bcm2835_reset_status,
+};
+
+static const char *const power_domain_names[] = {
+       [BCM2835_POWER_DOMAIN_GRAFX] = "grafx",
+       [BCM2835_POWER_DOMAIN_GRAFX_V3D] = "v3d",
+
+       [BCM2835_POWER_DOMAIN_IMAGE] = "image",
+       [BCM2835_POWER_DOMAIN_IMAGE_PERI] = "peri_image",
+       [BCM2835_POWER_DOMAIN_IMAGE_H264] = "h264",
+       [BCM2835_POWER_DOMAIN_IMAGE_ISP] = "isp",
+
+       [BCM2835_POWER_DOMAIN_USB] = "usb",
+       [BCM2835_POWER_DOMAIN_DSI0] = "dsi0",
+       [BCM2835_POWER_DOMAIN_DSI1] = "dsi1",
+       [BCM2835_POWER_DOMAIN_CAM0] = "cam0",
+       [BCM2835_POWER_DOMAIN_CAM1] = "cam1",
+       [BCM2835_POWER_DOMAIN_CCP2TX] = "ccp2tx",
+       [BCM2835_POWER_DOMAIN_HDMI] = "hdmi",
+};
+
+static int bcm2835_power_probe(struct platform_device *pdev)
+{
+       struct bcm2835_pm *pm = dev_get_drvdata(pdev->dev.parent);
+       struct device *dev = &pdev->dev;
+       struct bcm2835_power *power;
+       static const struct {
+               int parent, child;
+       } domain_deps[] = {
+               { BCM2835_POWER_DOMAIN_GRAFX, BCM2835_POWER_DOMAIN_GRAFX_V3D },
+               { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_PERI },
+               { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_H264 },
+               { BCM2835_POWER_DOMAIN_IMAGE, BCM2835_POWER_DOMAIN_IMAGE_ISP },
+               { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_USB },
+               { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM0 },
+               { BCM2835_POWER_DOMAIN_IMAGE_PERI, BCM2835_POWER_DOMAIN_CAM1 },
+       };
+       int ret = 0, i;
+       u32 id;
+
+       power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
+       if (!power)
+               return -ENOMEM;
+       platform_set_drvdata(pdev, power);
+
+       power->dev = dev;
+       power->base = pm->base;
+       power->asb = pm->asb;
+       power->rpivid_asb = pm->rpivid_asb;
+
+       id = readl(power->asb + ASB_AXI_BRDG_ID);
+       if (id != BCM2835_BRDG_ID /* "BRDG" */) {
+               dev_err(dev, "ASB register ID returned 0x%08x\n", id);
+               return -ENODEV;
+       }
+
+       if (power->rpivid_asb) {
+               id = readl(power->rpivid_asb + ASB_AXI_BRDG_ID);
+               if (id != BCM2835_BRDG_ID /* "BRDG" */) {
+                       dev_err(dev, "RPiVid ASB register ID returned 0x%08x\n",
+                                    id);
+                       return -ENODEV;
+               }
+       }
+
+       power->pd_xlate.domains = devm_kcalloc(dev,
+                                              ARRAY_SIZE(power_domain_names),
+                                              sizeof(*power->pd_xlate.domains),
+                                              GFP_KERNEL);
+       if (!power->pd_xlate.domains)
+               return -ENOMEM;
+
+       power->pd_xlate.num_domains = ARRAY_SIZE(power_domain_names);
+
+       for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) {
+               ret = bcm2835_init_power_domain(power, i, power_domain_names[i]);
+               if (ret)
+                       goto fail;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(domain_deps); i++) {
+               pm_genpd_add_subdomain(&power->domains[domain_deps[i].parent].base,
+                                      &power->domains[domain_deps[i].child].base);
+       }
+
+       power->reset.owner = THIS_MODULE;
+       power->reset.nr_resets = BCM2835_RESET_COUNT;
+       power->reset.ops = &bcm2835_reset_ops;
+       power->reset.of_node = dev->parent->of_node;
+
+       ret = devm_reset_controller_register(dev, &power->reset);
+       if (ret)
+               goto fail;
+
+       of_genpd_add_provider_onecell(dev->parent->of_node, &power->pd_xlate);
+
+       dev_info(dev, "Broadcom BCM2835 power domains driver");
+       return 0;
+
+fail:
+       for (i = 0; i < ARRAY_SIZE(power_domain_names); i++) {
+               struct generic_pm_domain *dom = &power->domains[i].base;
+
+               if (dom->name)
+                       pm_genpd_remove(dom);
+       }
+       return ret;
+}
+
+static struct platform_driver bcm2835_power_driver = {
+       .probe          = bcm2835_power_probe,
+       .driver = {
+               .name = "bcm2835-power",
+       },
+};
+module_platform_driver(bcm2835_power_driver);
+
+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
+MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset");
diff --git a/drivers/pmdomain/bcm/bcm63xx-power.c b/drivers/pmdomain/bcm/bcm63xx-power.c
new file mode 100644 (file)
index 0000000..98b0c24
--- /dev/null
@@ -0,0 +1,375 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * BCM63xx Power Domain Controller Driver
+ *
+ * Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
+ */
+
+#include <dt-bindings/soc/bcm6318-pm.h>
+#include <dt-bindings/soc/bcm6328-pm.h>
+#include <dt-bindings/soc/bcm6362-pm.h>
+#include <dt-bindings/soc/bcm63268-pm.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/of.h>
+
+struct bcm63xx_power_dev {
+       struct generic_pm_domain genpd;
+       struct bcm63xx_power *power;
+       uint32_t mask;
+};
+
+struct bcm63xx_power {
+       void __iomem *base;
+       spinlock_t lock;
+       struct bcm63xx_power_dev *dev;
+       struct genpd_onecell_data genpd_data;
+       struct generic_pm_domain **genpd;
+};
+
+struct bcm63xx_power_data {
+       const char * const name;
+       uint8_t bit;
+       unsigned int flags;
+};
+
+static int bcm63xx_power_get_state(struct bcm63xx_power_dev *pmd, bool *is_on)
+{
+       struct bcm63xx_power *power = pmd->power;
+
+       if (!pmd->mask) {
+               *is_on = false;
+               return -EINVAL;
+       }
+
+       *is_on = !(__raw_readl(power->base) & pmd->mask);
+
+       return 0;
+}
+
+static int bcm63xx_power_set_state(struct bcm63xx_power_dev *pmd, bool on)
+{
+       struct bcm63xx_power *power = pmd->power;
+       unsigned long flags;
+       uint32_t val;
+
+       if (!pmd->mask)
+               return -EINVAL;
+
+       spin_lock_irqsave(&power->lock, flags);
+       val = __raw_readl(power->base);
+       if (on)
+               val &= ~pmd->mask;
+       else
+               val |= pmd->mask;
+       __raw_writel(val, power->base);
+       spin_unlock_irqrestore(&power->lock, flags);
+
+       return 0;
+}
+
+static int bcm63xx_power_on(struct generic_pm_domain *genpd)
+{
+       struct bcm63xx_power_dev *pmd = container_of(genpd,
+               struct bcm63xx_power_dev, genpd);
+
+       return bcm63xx_power_set_state(pmd, true);
+}
+
+static int bcm63xx_power_off(struct generic_pm_domain *genpd)
+{
+       struct bcm63xx_power_dev *pmd = container_of(genpd,
+               struct bcm63xx_power_dev, genpd);
+
+       return bcm63xx_power_set_state(pmd, false);
+}
+
+static int bcm63xx_power_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       const struct bcm63xx_power_data *entry, *table;
+       struct bcm63xx_power *power;
+       unsigned int ndom;
+       uint8_t max_bit = 0;
+       int ret;
+
+       power = devm_kzalloc(dev, sizeof(*power), GFP_KERNEL);
+       if (!power)
+               return -ENOMEM;
+
+       power->base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(power->base))
+               return PTR_ERR(power->base);
+
+       table = of_device_get_match_data(dev);
+       if (!table)
+               return -EINVAL;
+
+       power->genpd_data.num_domains = 0;
+       ndom = 0;
+       for (entry = table; entry->name; entry++) {
+               max_bit = max(max_bit, entry->bit);
+               ndom++;
+       }
+
+       if (!ndom)
+               return -ENODEV;
+
+       power->genpd_data.num_domains = max_bit + 1;
+
+       power->dev = devm_kcalloc(dev, power->genpd_data.num_domains,
+                                 sizeof(struct bcm63xx_power_dev),
+                                 GFP_KERNEL);
+       if (!power->dev)
+               return -ENOMEM;
+
+       power->genpd = devm_kcalloc(dev, power->genpd_data.num_domains,
+                                   sizeof(struct generic_pm_domain *),
+                                   GFP_KERNEL);
+       if (!power->genpd)
+               return -ENOMEM;
+
+       power->genpd_data.domains = power->genpd;
+
+       ndom = 0;
+       for (entry = table; entry->name; entry++) {
+               struct bcm63xx_power_dev *pmd = &power->dev[ndom];
+               bool is_on;
+
+               pmd->power = power;
+               pmd->mask = BIT(entry->bit);
+               pmd->genpd.name = entry->name;
+               pmd->genpd.flags = entry->flags;
+
+               ret = bcm63xx_power_get_state(pmd, &is_on);
+               if (ret)
+                       dev_warn(dev, "unable to get current state for %s\n",
+                                pmd->genpd.name);
+
+               pmd->genpd.power_on = bcm63xx_power_on;
+               pmd->genpd.power_off = bcm63xx_power_off;
+
+               pm_genpd_init(&pmd->genpd, NULL, !is_on);
+               power->genpd[entry->bit] = &pmd->genpd;
+
+               ndom++;
+       }
+
+       spin_lock_init(&power->lock);
+
+       ret = of_genpd_add_provider_onecell(np, &power->genpd_data);
+       if (ret) {
+               dev_err(dev, "failed to register genpd driver: %d\n", ret);
+               return ret;
+       }
+
+       dev_info(dev, "registered %u power domains\n", ndom);
+
+       return 0;
+}
+
+static const struct bcm63xx_power_data bcm6318_power_domains[] = {
+       {
+               .name = "pcie",
+               .bit = BCM6318_POWER_DOMAIN_PCIE,
+       }, {
+               .name = "usb",
+               .bit = BCM6318_POWER_DOMAIN_USB,
+       }, {
+               .name = "ephy0",
+               .bit = BCM6318_POWER_DOMAIN_EPHY0,
+       }, {
+               .name = "ephy1",
+               .bit = BCM6318_POWER_DOMAIN_EPHY1,
+       }, {
+               .name = "ephy2",
+               .bit = BCM6318_POWER_DOMAIN_EPHY2,
+       }, {
+               .name = "ephy3",
+               .bit = BCM6318_POWER_DOMAIN_EPHY3,
+       }, {
+               .name = "ldo2p5",
+               .bit = BCM6318_POWER_DOMAIN_LDO2P5,
+               .flags = GENPD_FLAG_ALWAYS_ON,
+       }, {
+               .name = "ldo2p9",
+               .bit = BCM6318_POWER_DOMAIN_LDO2P9,
+               .flags = GENPD_FLAG_ALWAYS_ON,
+       }, {
+               .name = "sw1p0",
+               .bit = BCM6318_POWER_DOMAIN_SW1P0,
+               .flags = GENPD_FLAG_ALWAYS_ON,
+       }, {
+               .name = "pad",
+               .bit = BCM6318_POWER_DOMAIN_PAD,
+               .flags = GENPD_FLAG_ALWAYS_ON,
+       }, {
+               /* sentinel */
+       },
+};
+
+static const struct bcm63xx_power_data bcm6328_power_domains[] = {
+       {
+               .name = "adsl2-mips",
+               .bit = BCM6328_POWER_DOMAIN_ADSL2_MIPS,
+       }, {
+               .name = "adsl2-phy",
+               .bit = BCM6328_POWER_DOMAIN_ADSL2_PHY,
+       }, {
+               .name = "adsl2-afe",
+               .bit = BCM6328_POWER_DOMAIN_ADSL2_AFE,
+       }, {
+               .name = "sar",
+               .bit = BCM6328_POWER_DOMAIN_SAR,
+       }, {
+               .name = "pcm",
+               .bit = BCM6328_POWER_DOMAIN_PCM,
+       }, {
+               .name = "usbd",
+               .bit = BCM6328_POWER_DOMAIN_USBD,
+       }, {
+               .name = "usbh",
+               .bit = BCM6328_POWER_DOMAIN_USBH,
+       }, {
+               .name = "pcie",
+               .bit = BCM6328_POWER_DOMAIN_PCIE,
+       }, {
+               .name = "robosw",
+               .bit = BCM6328_POWER_DOMAIN_ROBOSW,
+       }, {
+               .name = "ephy",
+               .bit = BCM6328_POWER_DOMAIN_EPHY,
+       }, {
+               /* sentinel */
+       },
+};
+
+static const struct bcm63xx_power_data bcm6362_power_domains[] = {
+       {
+               .name = "sar",
+               .bit = BCM6362_POWER_DOMAIN_SAR,
+       }, {
+               .name = "ipsec",
+               .bit = BCM6362_POWER_DOMAIN_IPSEC,
+       }, {
+               .name = "mips",
+               .bit = BCM6362_POWER_DOMAIN_MIPS,
+               .flags = GENPD_FLAG_ALWAYS_ON,
+       }, {
+               .name = "dect",
+               .bit = BCM6362_POWER_DOMAIN_DECT,
+       }, {
+               .name = "usbh",
+               .bit = BCM6362_POWER_DOMAIN_USBH,
+       }, {
+               .name = "usbd",
+               .bit = BCM6362_POWER_DOMAIN_USBD,
+       }, {
+               .name = "robosw",
+               .bit = BCM6362_POWER_DOMAIN_ROBOSW,
+       }, {
+               .name = "pcm",
+               .bit = BCM6362_POWER_DOMAIN_PCM,
+       }, {
+               .name = "periph",
+               .bit = BCM6362_POWER_DOMAIN_PERIPH,
+               .flags = GENPD_FLAG_ALWAYS_ON,
+       }, {
+               .name = "adsl-phy",
+               .bit = BCM6362_POWER_DOMAIN_ADSL_PHY,
+       }, {
+               .name = "gmii-pads",
+               .bit = BCM6362_POWER_DOMAIN_GMII_PADS,
+       }, {
+               .name = "fap",
+               .bit = BCM6362_POWER_DOMAIN_FAP,
+       }, {
+               .name = "pcie",
+               .bit = BCM6362_POWER_DOMAIN_PCIE,
+       }, {
+               .name = "wlan-pads",
+               .bit = BCM6362_POWER_DOMAIN_WLAN_PADS,
+       }, {
+               /* sentinel */
+       },
+};
+
+static const struct bcm63xx_power_data bcm63268_power_domains[] = {
+       {
+               .name = "sar",
+               .bit = BCM63268_POWER_DOMAIN_SAR,
+       }, {
+               .name = "ipsec",
+               .bit = BCM63268_POWER_DOMAIN_IPSEC,
+       }, {
+               .name = "mips",
+               .bit = BCM63268_POWER_DOMAIN_MIPS,
+               .flags = GENPD_FLAG_ALWAYS_ON,
+       }, {
+               .name = "dect",
+               .bit = BCM63268_POWER_DOMAIN_DECT,
+       }, {
+               .name = "usbh",
+               .bit = BCM63268_POWER_DOMAIN_USBH,
+       }, {
+               .name = "usbd",
+               .bit = BCM63268_POWER_DOMAIN_USBD,
+       }, {
+               .name = "robosw",
+               .bit = BCM63268_POWER_DOMAIN_ROBOSW,
+       }, {
+               .name = "pcm",
+               .bit = BCM63268_POWER_DOMAIN_PCM,
+       }, {
+               .name = "periph",
+               .bit = BCM63268_POWER_DOMAIN_PERIPH,
+               .flags = GENPD_FLAG_ALWAYS_ON,
+       }, {
+               .name = "vdsl-phy",
+               .bit = BCM63268_POWER_DOMAIN_VDSL_PHY,
+       }, {
+               .name = "vdsl-mips",
+               .bit = BCM63268_POWER_DOMAIN_VDSL_MIPS,
+       }, {
+               .name = "fap",
+               .bit = BCM63268_POWER_DOMAIN_FAP,
+       }, {
+               .name = "pcie",
+               .bit = BCM63268_POWER_DOMAIN_PCIE,
+       }, {
+               .name = "wlan-pads",
+               .bit = BCM63268_POWER_DOMAIN_WLAN_PADS,
+       }, {
+               /* sentinel */
+       },
+};
+
+static const struct of_device_id bcm63xx_power_of_match[] = {
+       {
+               .compatible = "brcm,bcm6318-power-controller",
+               .data = &bcm6318_power_domains,
+       }, {
+               .compatible = "brcm,bcm6328-power-controller",
+               .data = &bcm6328_power_domains,
+       }, {
+               .compatible = "brcm,bcm6362-power-controller",
+               .data = &bcm6362_power_domains,
+       }, {
+               .compatible = "brcm,bcm63268-power-controller",
+               .data = &bcm63268_power_domains,
+       }, {
+               /* sentinel */
+       }
+};
+
+static struct platform_driver bcm63xx_power_driver = {
+       .driver = {
+               .name = "bcm63xx-power-controller",
+               .of_match_table = bcm63xx_power_of_match,
+       },
+       .probe  = bcm63xx_power_probe,
+};
+builtin_platform_driver(bcm63xx_power_driver);
diff --git a/drivers/pmdomain/bcm/raspberrypi-power.c b/drivers/pmdomain/bcm/raspberrypi-power.c
new file mode 100644 (file)
index 0000000..06196eb
--- /dev/null
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0
+/* (C) 2015 Pengutronix, Alexander Aring <aar@pengutronix.de>
+ *
+ * Authors:
+ * Alexander Aring <aar@pengutronix.de>
+ * Eric Anholt <eric@anholt.net>
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <dt-bindings/power/raspberrypi-power.h>
+#include <soc/bcm2835/raspberrypi-firmware.h>
+
+/*
+ * Firmware indices for the old power domains interface.  Only a few
+ * of them were actually implemented.
+ */
+#define RPI_OLD_POWER_DOMAIN_USB               3
+#define RPI_OLD_POWER_DOMAIN_V3D               10
+
+struct rpi_power_domain {
+       u32 domain;
+       bool enabled;
+       bool old_interface;
+       struct generic_pm_domain base;
+       struct rpi_firmware *fw;
+};
+
+struct rpi_power_domains {
+       bool has_new_interface;
+       struct genpd_onecell_data xlate;
+       struct rpi_firmware *fw;
+       struct rpi_power_domain domains[RPI_POWER_DOMAIN_COUNT];
+};
+
+/*
+ * Packet definition used by RPI_FIRMWARE_SET_POWER_STATE and
+ * RPI_FIRMWARE_SET_DOMAIN_STATE
+ */
+struct rpi_power_domain_packet {
+       u32 domain;
+       u32 on;
+};
+
+/*
+ * Asks the firmware to enable or disable power on a specific power
+ * domain.
+ */
+static int rpi_firmware_set_power(struct rpi_power_domain *rpi_domain, bool on)
+{
+       struct rpi_power_domain_packet packet;
+
+       packet.domain = rpi_domain->domain;
+       packet.on = on;
+       return rpi_firmware_property(rpi_domain->fw,
+                                    rpi_domain->old_interface ?
+                                    RPI_FIRMWARE_SET_POWER_STATE :
+                                    RPI_FIRMWARE_SET_DOMAIN_STATE,
+                                    &packet, sizeof(packet));
+}
+
+static int rpi_domain_off(struct generic_pm_domain *domain)
+{
+       struct rpi_power_domain *rpi_domain =
+               container_of(domain, struct rpi_power_domain, base);
+
+       return rpi_firmware_set_power(rpi_domain, false);
+}
+
+static int rpi_domain_on(struct generic_pm_domain *domain)
+{
+       struct rpi_power_domain *rpi_domain =
+               container_of(domain, struct rpi_power_domain, base);
+
+       return rpi_firmware_set_power(rpi_domain, true);
+}
+
+static void rpi_common_init_power_domain(struct rpi_power_domains *rpi_domains,
+                                        int xlate_index, const char *name)
+{
+       struct rpi_power_domain *dom = &rpi_domains->domains[xlate_index];
+
+       dom->fw = rpi_domains->fw;
+
+       dom->base.name = name;
+       dom->base.power_on = rpi_domain_on;
+       dom->base.power_off = rpi_domain_off;
+
+       /*
+        * Treat all power domains as off at boot.
+        *
+        * The firmware itself may be keeping some domains on, but
+        * from Linux's perspective all we control is the refcounts
+        * that we give to the firmware, and we can't ask the firmware
+        * to turn off something that we haven't ourselves turned on.
+        */
+       pm_genpd_init(&dom->base, NULL, true);
+
+       rpi_domains->xlate.domains[xlate_index] = &dom->base;
+}
+
+static void rpi_init_power_domain(struct rpi_power_domains *rpi_domains,
+                                 int xlate_index, const char *name)
+{
+       struct rpi_power_domain *dom = &rpi_domains->domains[xlate_index];
+
+       if (!rpi_domains->has_new_interface)
+               return;
+
+       /* The DT binding index is the firmware's domain index minus one. */
+       dom->domain = xlate_index + 1;
+
+       rpi_common_init_power_domain(rpi_domains, xlate_index, name);
+}
+
+static void rpi_init_old_power_domain(struct rpi_power_domains *rpi_domains,
+                                     int xlate_index, int domain,
+                                     const char *name)
+{
+       struct rpi_power_domain *dom = &rpi_domains->domains[xlate_index];
+
+       dom->old_interface = true;
+       dom->domain = domain;
+
+       rpi_common_init_power_domain(rpi_domains, xlate_index, name);
+}
+
+/*
+ * Detects whether the firmware supports the new power domains interface.
+ *
+ * The firmware doesn't actually return an error on an unknown tag,
+ * and just skips over it, so we do the detection by putting an
+ * unexpected value in the return field and checking if it was
+ * unchanged.
+ */
+static bool
+rpi_has_new_domain_support(struct rpi_power_domains *rpi_domains)
+{
+       struct rpi_power_domain_packet packet;
+       int ret;
+
+       packet.domain = RPI_POWER_DOMAIN_ARM;
+       packet.on = ~0;
+
+       ret = rpi_firmware_property(rpi_domains->fw,
+                                   RPI_FIRMWARE_GET_DOMAIN_STATE,
+                                   &packet, sizeof(packet));
+
+       return ret == 0 && packet.on != ~0;
+}
+
+static int rpi_power_probe(struct platform_device *pdev)
+{
+       struct device_node *fw_np;
+       struct device *dev = &pdev->dev;
+       struct rpi_power_domains *rpi_domains;
+
+       rpi_domains = devm_kzalloc(dev, sizeof(*rpi_domains), GFP_KERNEL);
+       if (!rpi_domains)
+               return -ENOMEM;
+
+       rpi_domains->xlate.domains =
+               devm_kcalloc(dev,
+                            RPI_POWER_DOMAIN_COUNT,
+                            sizeof(*rpi_domains->xlate.domains),
+                            GFP_KERNEL);
+       if (!rpi_domains->xlate.domains)
+               return -ENOMEM;
+
+       rpi_domains->xlate.num_domains = RPI_POWER_DOMAIN_COUNT;
+
+       fw_np = of_parse_phandle(pdev->dev.of_node, "firmware", 0);
+       if (!fw_np) {
+               dev_err(&pdev->dev, "no firmware node\n");
+               return -ENODEV;
+       }
+
+       rpi_domains->fw = devm_rpi_firmware_get(&pdev->dev, fw_np);
+       of_node_put(fw_np);
+       if (!rpi_domains->fw)
+               return -EPROBE_DEFER;
+
+       rpi_domains->has_new_interface =
+               rpi_has_new_domain_support(rpi_domains);
+
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C0, "I2C0");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C1, "I2C1");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C2, "I2C2");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VIDEO_SCALER,
+                             "VIDEO_SCALER");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VPU1, "VPU1");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_HDMI, "HDMI");
+
+       /*
+        * Use the old firmware interface for USB power, so that we
+        * can turn it on even if the firmware hasn't been updated.
+        */
+       rpi_init_old_power_domain(rpi_domains, RPI_POWER_DOMAIN_USB,
+                                 RPI_OLD_POWER_DOMAIN_USB, "USB");
+
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VEC, "VEC");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_JPEG, "JPEG");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_H264, "H264");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_V3D, "V3D");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_ISP, "ISP");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_UNICAM0, "UNICAM0");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_UNICAM1, "UNICAM1");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CCP2RX, "CCP2RX");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CSI2, "CSI2");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CPI, "CPI");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_DSI0, "DSI0");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_DSI1, "DSI1");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_TRANSPOSER,
+                             "TRANSPOSER");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CCP2TX, "CCP2TX");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CDP, "CDP");
+       rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_ARM, "ARM");
+
+       of_genpd_add_provider_onecell(dev->of_node, &rpi_domains->xlate);
+
+       platform_set_drvdata(pdev, rpi_domains);
+
+       return 0;
+}
+
+static const struct of_device_id rpi_power_of_match[] = {
+       { .compatible = "raspberrypi,bcm2835-power", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, rpi_power_of_match);
+
+static struct platform_driver rpi_power_driver = {
+       .driver = {
+               .name = "raspberrypi-power",
+               .of_match_table = rpi_power_of_match,
+       },
+       .probe          = rpi_power_probe,
+};
+builtin_platform_driver(rpi_power_driver);
+
+MODULE_AUTHOR("Alexander Aring <aar@pengutronix.de>");
+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
+MODULE_DESCRIPTION("Raspberry Pi power domain driver");
diff --git a/drivers/pmdomain/imx/Makefile b/drivers/pmdomain/imx/Makefile
new file mode 100644 (file)
index 0000000..52d2629
--- /dev/null
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
+obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
+obj-$(CONFIG_IMX_SCU_PD) += scu-pd.o
+obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8m-blk-ctrl.o
+obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8mp-blk-ctrl.o
+obj-$(CONFIG_SOC_IMX9) += imx93-pd.o
+obj-$(CONFIG_IMX9_BLK_CTRL) += imx93-blk-ctrl.o
diff --git a/drivers/pmdomain/imx/gpc.c b/drivers/pmdomain/imx/gpc.c
new file mode 100644 (file)
index 0000000..90a8b2c
--- /dev/null
@@ -0,0 +1,554 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
+ * Copyright 2011-2013 Freescale Semiconductor, Inc.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#define GPC_CNTR               0x000
+
+#define GPC_PGC_CTRL_OFFS      0x0
+#define GPC_PGC_PUPSCR_OFFS    0x4
+#define GPC_PGC_PDNSCR_OFFS    0x8
+#define GPC_PGC_SW2ISO_SHIFT   0x8
+#define GPC_PGC_SW_SHIFT       0x0
+
+#define GPC_PGC_PCI_PDN                0x200
+#define GPC_PGC_PCI_SR         0x20c
+
+#define GPC_PGC_GPU_PDN                0x260
+#define GPC_PGC_GPU_PUPSCR     0x264
+#define GPC_PGC_GPU_PDNSCR     0x268
+#define GPC_PGC_GPU_SR         0x26c
+
+#define GPC_PGC_DISP_PDN       0x240
+#define GPC_PGC_DISP_SR                0x24c
+
+#define GPU_VPU_PUP_REQ                BIT(1)
+#define GPU_VPU_PDN_REQ                BIT(0)
+
+#define GPC_CLK_MAX            7
+
+#define PGC_DOMAIN_FLAG_NO_PD          BIT(0)
+
+struct imx_pm_domain {
+       struct generic_pm_domain base;
+       struct regmap *regmap;
+       struct regulator *supply;
+       struct clk *clk[GPC_CLK_MAX];
+       int num_clks;
+       unsigned int reg_offs;
+       signed char cntr_pdn_bit;
+       unsigned int ipg_rate_mhz;
+};
+
+static inline struct imx_pm_domain *
+to_imx_pm_domain(struct generic_pm_domain *genpd)
+{
+       return container_of(genpd, struct imx_pm_domain, base);
+}
+
+static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd)
+{
+       struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
+       int iso, iso2sw;
+       u32 val;
+
+       /* Read ISO and ISO2SW power down delays */
+       regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PDNSCR_OFFS, &val);
+       iso = val & 0x3f;
+       iso2sw = (val >> 8) & 0x3f;
+
+       /* Gate off domain when powered down */
+       regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
+                          0x1, 0x1);
+
+       /* Request GPC to power down domain */
+       val = BIT(pd->cntr_pdn_bit);
+       regmap_update_bits(pd->regmap, GPC_CNTR, val, val);
+
+       /* Wait ISO + ISO2SW IPG clock cycles */
+       udelay(DIV_ROUND_UP(iso + iso2sw, pd->ipg_rate_mhz));
+
+       if (pd->supply)
+               regulator_disable(pd->supply);
+
+       return 0;
+}
+
+static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd)
+{
+       struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
+       int i, ret;
+       u32 val, req;
+
+       if (pd->supply) {
+               ret = regulator_enable(pd->supply);
+               if (ret) {
+                       pr_err("%s: failed to enable regulator: %d\n",
+                              __func__, ret);
+                       return ret;
+               }
+       }
+
+       /* Enable reset clocks for all devices in the domain */
+       for (i = 0; i < pd->num_clks; i++)
+               clk_prepare_enable(pd->clk[i]);
+
+       /* Gate off domain when powered down */
+       regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
+                          0x1, 0x1);
+
+       /* Request GPC to power up domain */
+       req = BIT(pd->cntr_pdn_bit + 1);
+       regmap_update_bits(pd->regmap, GPC_CNTR, req, req);
+
+       /* Wait for the PGC to handle the request */
+       ret = regmap_read_poll_timeout(pd->regmap, GPC_CNTR, val, !(val & req),
+                                      1, 50);
+       if (ret)
+               pr_err("powerup request on domain %s timed out\n", genpd->name);
+
+       /* Wait for reset to propagate through peripherals */
+       usleep_range(5, 10);
+
+       /* Disable reset clocks for all devices in the domain */
+       for (i = 0; i < pd->num_clks; i++)
+               clk_disable_unprepare(pd->clk[i]);
+
+       return 0;
+}
+
+static int imx_pgc_get_clocks(struct device *dev, struct imx_pm_domain *domain)
+{
+       int i, ret;
+
+       for (i = 0; ; i++) {
+               struct clk *clk = of_clk_get(dev->of_node, i);
+               if (IS_ERR(clk))
+                       break;
+               if (i >= GPC_CLK_MAX) {
+                       dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX);
+                       ret = -EINVAL;
+                       goto clk_err;
+               }
+               domain->clk[i] = clk;
+       }
+       domain->num_clks = i;
+
+       return 0;
+
+clk_err:
+       while (i--)
+               clk_put(domain->clk[i]);
+
+       return ret;
+}
+
+static void imx_pgc_put_clocks(struct imx_pm_domain *domain)
+{
+       int i;
+
+       for (i = domain->num_clks - 1; i >= 0; i--)
+               clk_put(domain->clk[i]);
+}
+
+static int imx_pgc_parse_dt(struct device *dev, struct imx_pm_domain *domain)
+{
+       /* try to get the domain supply regulator */
+       domain->supply = devm_regulator_get_optional(dev, "power");
+       if (IS_ERR(domain->supply)) {
+               if (PTR_ERR(domain->supply) == -ENODEV)
+                       domain->supply = NULL;
+               else
+                       return PTR_ERR(domain->supply);
+       }
+
+       /* try to get all clocks needed for reset propagation */
+       return imx_pgc_get_clocks(dev, domain);
+}
+
+static int imx_pgc_power_domain_probe(struct platform_device *pdev)
+{
+       struct imx_pm_domain *domain = pdev->dev.platform_data;
+       struct device *dev = &pdev->dev;
+       int ret;
+
+       /* if this PD is associated with a DT node try to parse it */
+       if (dev->of_node) {
+               ret = imx_pgc_parse_dt(dev, domain);
+               if (ret)
+                       return ret;
+       }
+
+       /* initially power on the domain */
+       if (domain->base.power_on)
+               domain->base.power_on(&domain->base);
+
+       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
+               pm_genpd_init(&domain->base, NULL, false);
+               ret = of_genpd_add_provider_simple(dev->of_node, &domain->base);
+               if (ret)
+                       goto genpd_err;
+       }
+
+       device_link_add(dev, dev->parent, DL_FLAG_AUTOREMOVE_CONSUMER);
+
+       return 0;
+
+genpd_err:
+       pm_genpd_remove(&domain->base);
+       imx_pgc_put_clocks(domain);
+
+       return ret;
+}
+
+static int imx_pgc_power_domain_remove(struct platform_device *pdev)
+{
+       struct imx_pm_domain *domain = pdev->dev.platform_data;
+
+       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
+               of_genpd_del_provider(pdev->dev.of_node);
+               pm_genpd_remove(&domain->base);
+               imx_pgc_put_clocks(domain);
+       }
+
+       return 0;
+}
+
+static const struct platform_device_id imx_pgc_power_domain_id[] = {
+       { "imx-pgc-power-domain"},
+       { },
+};
+
+static struct platform_driver imx_pgc_power_domain_driver = {
+       .driver = {
+               .name = "imx-pgc-pd",
+       },
+       .probe = imx_pgc_power_domain_probe,
+       .remove = imx_pgc_power_domain_remove,
+       .id_table = imx_pgc_power_domain_id,
+};
+builtin_platform_driver(imx_pgc_power_domain_driver)
+
+#define GPC_PGC_DOMAIN_ARM     0
+#define GPC_PGC_DOMAIN_PU      1
+#define GPC_PGC_DOMAIN_DISPLAY 2
+#define GPC_PGC_DOMAIN_PCI     3
+
+static struct genpd_power_state imx6_pm_domain_pu_state = {
+       .power_off_latency_ns = 25000,
+       .power_on_latency_ns = 2000000,
+};
+
+static struct imx_pm_domain imx_gpc_domains[] = {
+       [GPC_PGC_DOMAIN_ARM] = {
+               .base = {
+                       .name = "ARM",
+                       .flags = GENPD_FLAG_ALWAYS_ON,
+               },
+       },
+       [GPC_PGC_DOMAIN_PU] = {
+               .base = {
+                       .name = "PU",
+                       .power_off = imx6_pm_domain_power_off,
+                       .power_on = imx6_pm_domain_power_on,
+                       .states = &imx6_pm_domain_pu_state,
+                       .state_count = 1,
+               },
+               .reg_offs = 0x260,
+               .cntr_pdn_bit = 0,
+       },
+       [GPC_PGC_DOMAIN_DISPLAY] = {
+               .base = {
+                       .name = "DISPLAY",
+                       .power_off = imx6_pm_domain_power_off,
+                       .power_on = imx6_pm_domain_power_on,
+               },
+               .reg_offs = 0x240,
+               .cntr_pdn_bit = 4,
+       },
+       [GPC_PGC_DOMAIN_PCI] = {
+               .base = {
+                       .name = "PCI",
+                       .power_off = imx6_pm_domain_power_off,
+                       .power_on = imx6_pm_domain_power_on,
+               },
+               .reg_offs = 0x200,
+               .cntr_pdn_bit = 6,
+       },
+};
+
+struct imx_gpc_dt_data {
+       int num_domains;
+       bool err009619_present;
+       bool err006287_present;
+};
+
+static const struct imx_gpc_dt_data imx6q_dt_data = {
+       .num_domains = 2,
+       .err009619_present = false,
+       .err006287_present = false,
+};
+
+static const struct imx_gpc_dt_data imx6qp_dt_data = {
+       .num_domains = 2,
+       .err009619_present = true,
+       .err006287_present = false,
+};
+
+static const struct imx_gpc_dt_data imx6sl_dt_data = {
+       .num_domains = 3,
+       .err009619_present = false,
+       .err006287_present = true,
+};
+
+static const struct imx_gpc_dt_data imx6sx_dt_data = {
+       .num_domains = 4,
+       .err009619_present = false,
+       .err006287_present = false,
+};
+
+static const struct of_device_id imx_gpc_dt_ids[] = {
+       { .compatible = "fsl,imx6q-gpc", .data = &imx6q_dt_data },
+       { .compatible = "fsl,imx6qp-gpc", .data = &imx6qp_dt_data },
+       { .compatible = "fsl,imx6sl-gpc", .data = &imx6sl_dt_data },
+       { .compatible = "fsl,imx6sx-gpc", .data = &imx6sx_dt_data },
+       { }
+};
+
+static const struct regmap_range yes_ranges[] = {
+       regmap_reg_range(GPC_CNTR, GPC_CNTR),
+       regmap_reg_range(GPC_PGC_PCI_PDN, GPC_PGC_PCI_SR),
+       regmap_reg_range(GPC_PGC_GPU_PDN, GPC_PGC_GPU_SR),
+       regmap_reg_range(GPC_PGC_DISP_PDN, GPC_PGC_DISP_SR),
+};
+
+static const struct regmap_access_table access_table = {
+       .yes_ranges     = yes_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(yes_ranges),
+};
+
+static const struct regmap_config imx_gpc_regmap_config = {
+       .reg_bits = 32,
+       .val_bits = 32,
+       .reg_stride = 4,
+       .rd_table = &access_table,
+       .wr_table = &access_table,
+       .max_register = 0x2ac,
+       .fast_io = true,
+};
+
+static struct generic_pm_domain *imx_gpc_onecell_domains[] = {
+       &imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base,
+       &imx_gpc_domains[GPC_PGC_DOMAIN_PU].base,
+};
+
+static struct genpd_onecell_data imx_gpc_onecell_data = {
+       .domains = imx_gpc_onecell_domains,
+       .num_domains = 2,
+};
+
+static int imx_gpc_old_dt_init(struct device *dev, struct regmap *regmap,
+                              unsigned int num_domains)
+{
+       struct imx_pm_domain *domain;
+       int i, ret;
+
+       for (i = 0; i < num_domains; i++) {
+               domain = &imx_gpc_domains[i];
+               domain->regmap = regmap;
+               domain->ipg_rate_mhz = 66;
+
+               if (i == 1) {
+                       domain->supply = devm_regulator_get(dev, "pu");
+                       if (IS_ERR(domain->supply))
+                               return PTR_ERR(domain->supply);
+
+                       ret = imx_pgc_get_clocks(dev, domain);
+                       if (ret)
+                               goto clk_err;
+
+                       domain->base.power_on(&domain->base);
+               }
+       }
+
+       for (i = 0; i < num_domains; i++)
+               pm_genpd_init(&imx_gpc_domains[i].base, NULL, false);
+
+       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
+               ret = of_genpd_add_provider_onecell(dev->of_node,
+                                                   &imx_gpc_onecell_data);
+               if (ret)
+                       goto genpd_err;
+       }
+
+       return 0;
+
+genpd_err:
+       for (i = 0; i < num_domains; i++)
+               pm_genpd_remove(&imx_gpc_domains[i].base);
+       imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
+clk_err:
+       return ret;
+}
+
+static int imx_gpc_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *of_id =
+                       of_match_device(imx_gpc_dt_ids, &pdev->dev);
+       const struct imx_gpc_dt_data *of_id_data = of_id->data;
+       struct device_node *pgc_node;
+       struct regmap *regmap;
+       void __iomem *base;
+       int ret;
+
+       pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
+
+       /* bail out if DT too old and doesn't provide the necessary info */
+       if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
+           !pgc_node)
+               return 0;
+
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base,
+                                          &imx_gpc_regmap_config);
+       if (IS_ERR(regmap)) {
+               ret = PTR_ERR(regmap);
+               dev_err(&pdev->dev, "failed to init regmap: %d\n",
+                       ret);
+               return ret;
+       }
+
+       /*
+        * Disable PU power down by runtime PM if ERR009619 is present.
+        *
+        * The PRE clock will be paused for several cycles when turning on the
+        * PU domain LDO from power down state. If PRE is in use at that time,
+        * the IPU/PRG cannot get the correct display data from the PRE.
+        *
+        * This is not a concern when the whole system enters suspend state, so
+        * it's safe to power down PU in this case.
+        */
+       if (of_id_data->err009619_present)
+               imx_gpc_domains[GPC_PGC_DOMAIN_PU].base.flags |=
+                               GENPD_FLAG_RPM_ALWAYS_ON;
+
+       /* Keep DISP always on if ERR006287 is present */
+       if (of_id_data->err006287_present)
+               imx_gpc_domains[GPC_PGC_DOMAIN_DISPLAY].base.flags |=
+                               GENPD_FLAG_ALWAYS_ON;
+
+       if (!pgc_node) {
+               ret = imx_gpc_old_dt_init(&pdev->dev, regmap,
+                                         of_id_data->num_domains);
+               if (ret)
+                       return ret;
+       } else {
+               struct imx_pm_domain *domain;
+               struct platform_device *pd_pdev;
+               struct device_node *np;
+               struct clk *ipg_clk;
+               unsigned int ipg_rate_mhz;
+               int domain_index;
+
+               ipg_clk = devm_clk_get(&pdev->dev, "ipg");
+               if (IS_ERR(ipg_clk))
+                       return PTR_ERR(ipg_clk);
+               ipg_rate_mhz = clk_get_rate(ipg_clk) / 1000000;
+
+               for_each_child_of_node(pgc_node, np) {
+                       ret = of_property_read_u32(np, "reg", &domain_index);
+                       if (ret) {
+                               of_node_put(np);
+                               return ret;
+                       }
+                       if (domain_index >= of_id_data->num_domains)
+                               continue;
+
+                       pd_pdev = platform_device_alloc("imx-pgc-power-domain",
+                                                       domain_index);
+                       if (!pd_pdev) {
+                               of_node_put(np);
+                               return -ENOMEM;
+                       }
+
+                       ret = platform_device_add_data(pd_pdev,
+                                                      &imx_gpc_domains[domain_index],
+                                                      sizeof(imx_gpc_domains[domain_index]));
+                       if (ret) {
+                               platform_device_put(pd_pdev);
+                               of_node_put(np);
+                               return ret;
+                       }
+                       domain = pd_pdev->dev.platform_data;
+                       domain->regmap = regmap;
+                       domain->ipg_rate_mhz = ipg_rate_mhz;
+
+                       pd_pdev->dev.parent = &pdev->dev;
+                       pd_pdev->dev.of_node = np;
+
+                       ret = platform_device_add(pd_pdev);
+                       if (ret) {
+                               platform_device_put(pd_pdev);
+                               of_node_put(np);
+                               return ret;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int imx_gpc_remove(struct platform_device *pdev)
+{
+       struct device_node *pgc_node;
+       int ret;
+
+       pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
+
+       /* bail out if DT too old and doesn't provide the necessary info */
+       if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
+           !pgc_node)
+               return 0;
+
+       /*
+        * If the old DT binding is used the toplevel driver needs to
+        * de-register the power domains
+        */
+       if (!pgc_node) {
+               of_genpd_del_provider(pdev->dev.of_node);
+
+               ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_PU].base);
+               if (ret)
+                       return ret;
+               imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
+
+               ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static struct platform_driver imx_gpc_driver = {
+       .driver = {
+               .name = "imx-gpc",
+               .of_match_table = imx_gpc_dt_ids,
+       },
+       .probe = imx_gpc_probe,
+       .remove = imx_gpc_remove,
+};
+builtin_platform_driver(imx_gpc_driver)
diff --git a/drivers/pmdomain/imx/gpcv2.c b/drivers/pmdomain/imx/gpcv2.c
new file mode 100644 (file)
index 0000000..fbd3d92
--- /dev/null
@@ -0,0 +1,1550 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2017 Impinj, Inc
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * Based on the code of analogus driver:
+ *
+ * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
+ */
+
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/sizes.h>
+#include <dt-bindings/power/imx7-power.h>
+#include <dt-bindings/power/imx8mq-power.h>
+#include <dt-bindings/power/imx8mm-power.h>
+#include <dt-bindings/power/imx8mn-power.h>
+#include <dt-bindings/power/imx8mp-power.h>
+
+#define GPC_LPCR_A_CORE_BSC                    0x000
+
+#define GPC_PGC_CPU_MAPPING            0x0ec
+#define IMX8MP_GPC_PGC_CPU_MAPPING     0x1cc
+
+#define IMX7_USB_HSIC_PHY_A_CORE_DOMAIN                BIT(6)
+#define IMX7_USB_OTG2_PHY_A_CORE_DOMAIN                BIT(5)
+#define IMX7_USB_OTG1_PHY_A_CORE_DOMAIN                BIT(4)
+#define IMX7_PCIE_PHY_A_CORE_DOMAIN            BIT(3)
+#define IMX7_MIPI_PHY_A_CORE_DOMAIN            BIT(2)
+
+#define IMX8M_PCIE2_A53_DOMAIN                 BIT(15)
+#define IMX8M_MIPI_CSI2_A53_DOMAIN             BIT(14)
+#define IMX8M_MIPI_CSI1_A53_DOMAIN             BIT(13)
+#define IMX8M_DISP_A53_DOMAIN                  BIT(12)
+#define IMX8M_HDMI_A53_DOMAIN                  BIT(11)
+#define IMX8M_VPU_A53_DOMAIN                   BIT(10)
+#define IMX8M_GPU_A53_DOMAIN                   BIT(9)
+#define IMX8M_DDR2_A53_DOMAIN                  BIT(8)
+#define IMX8M_DDR1_A53_DOMAIN                  BIT(7)
+#define IMX8M_OTG2_A53_DOMAIN                  BIT(5)
+#define IMX8M_OTG1_A53_DOMAIN                  BIT(4)
+#define IMX8M_PCIE1_A53_DOMAIN                 BIT(3)
+#define IMX8M_MIPI_A53_DOMAIN                  BIT(2)
+
+#define IMX8MM_VPUH1_A53_DOMAIN                        BIT(15)
+#define IMX8MM_VPUG2_A53_DOMAIN                        BIT(14)
+#define IMX8MM_VPUG1_A53_DOMAIN                        BIT(13)
+#define IMX8MM_DISPMIX_A53_DOMAIN              BIT(12)
+#define IMX8MM_VPUMIX_A53_DOMAIN               BIT(10)
+#define IMX8MM_GPUMIX_A53_DOMAIN               BIT(9)
+#define IMX8MM_GPU_A53_DOMAIN                  (BIT(8) | BIT(11))
+#define IMX8MM_DDR1_A53_DOMAIN                 BIT(7)
+#define IMX8MM_OTG2_A53_DOMAIN                 BIT(5)
+#define IMX8MM_OTG1_A53_DOMAIN                 BIT(4)
+#define IMX8MM_PCIE_A53_DOMAIN                 BIT(3)
+#define IMX8MM_MIPI_A53_DOMAIN                 BIT(2)
+
+#define IMX8MN_DISPMIX_A53_DOMAIN              BIT(12)
+#define IMX8MN_GPUMIX_A53_DOMAIN               BIT(9)
+#define IMX8MN_DDR1_A53_DOMAIN         BIT(7)
+#define IMX8MN_OTG1_A53_DOMAIN         BIT(4)
+#define IMX8MN_MIPI_A53_DOMAIN         BIT(2)
+
+#define IMX8MP_MEDIA_ISPDWP_A53_DOMAIN BIT(20)
+#define IMX8MP_HSIOMIX_A53_DOMAIN              BIT(19)
+#define IMX8MP_MIPI_PHY2_A53_DOMAIN            BIT(18)
+#define IMX8MP_HDMI_PHY_A53_DOMAIN             BIT(17)
+#define IMX8MP_HDMIMIX_A53_DOMAIN              BIT(16)
+#define IMX8MP_VPU_VC8000E_A53_DOMAIN          BIT(15)
+#define IMX8MP_VPU_G2_A53_DOMAIN               BIT(14)
+#define IMX8MP_VPU_G1_A53_DOMAIN               BIT(13)
+#define IMX8MP_MEDIAMIX_A53_DOMAIN             BIT(12)
+#define IMX8MP_GPU3D_A53_DOMAIN                        BIT(11)
+#define IMX8MP_VPUMIX_A53_DOMAIN               BIT(10)
+#define IMX8MP_GPUMIX_A53_DOMAIN               BIT(9)
+#define IMX8MP_GPU2D_A53_DOMAIN                        BIT(8)
+#define IMX8MP_AUDIOMIX_A53_DOMAIN             BIT(7)
+#define IMX8MP_MLMIX_A53_DOMAIN                        BIT(6)
+#define IMX8MP_USB2_PHY_A53_DOMAIN             BIT(5)
+#define IMX8MP_USB1_PHY_A53_DOMAIN             BIT(4)
+#define IMX8MP_PCIE_PHY_A53_DOMAIN             BIT(3)
+#define IMX8MP_MIPI_PHY1_A53_DOMAIN            BIT(2)
+
+#define IMX8MP_GPC_PU_PGC_SW_PUP_REQ   0x0d8
+#define IMX8MP_GPC_PU_PGC_SW_PDN_REQ   0x0e4
+
+#define GPC_PU_PGC_SW_PUP_REQ          0x0f8
+#define GPC_PU_PGC_SW_PDN_REQ          0x104
+
+#define IMX7_USB_HSIC_PHY_SW_Pxx_REQ           BIT(4)
+#define IMX7_USB_OTG2_PHY_SW_Pxx_REQ           BIT(3)
+#define IMX7_USB_OTG1_PHY_SW_Pxx_REQ           BIT(2)
+#define IMX7_PCIE_PHY_SW_Pxx_REQ               BIT(1)
+#define IMX7_MIPI_PHY_SW_Pxx_REQ               BIT(0)
+
+#define IMX8M_PCIE2_SW_Pxx_REQ                 BIT(13)
+#define IMX8M_MIPI_CSI2_SW_Pxx_REQ             BIT(12)
+#define IMX8M_MIPI_CSI1_SW_Pxx_REQ             BIT(11)
+#define IMX8M_DISP_SW_Pxx_REQ                  BIT(10)
+#define IMX8M_HDMI_SW_Pxx_REQ                  BIT(9)
+#define IMX8M_VPU_SW_Pxx_REQ                   BIT(8)
+#define IMX8M_GPU_SW_Pxx_REQ                   BIT(7)
+#define IMX8M_DDR2_SW_Pxx_REQ                  BIT(6)
+#define IMX8M_DDR1_SW_Pxx_REQ                  BIT(5)
+#define IMX8M_OTG2_SW_Pxx_REQ                  BIT(3)
+#define IMX8M_OTG1_SW_Pxx_REQ                  BIT(2)
+#define IMX8M_PCIE1_SW_Pxx_REQ                 BIT(1)
+#define IMX8M_MIPI_SW_Pxx_REQ                  BIT(0)
+
+#define IMX8MM_VPUH1_SW_Pxx_REQ                        BIT(13)
+#define IMX8MM_VPUG2_SW_Pxx_REQ                        BIT(12)
+#define IMX8MM_VPUG1_SW_Pxx_REQ                        BIT(11)
+#define IMX8MM_DISPMIX_SW_Pxx_REQ              BIT(10)
+#define IMX8MM_VPUMIX_SW_Pxx_REQ               BIT(8)
+#define IMX8MM_GPUMIX_SW_Pxx_REQ               BIT(7)
+#define IMX8MM_GPU_SW_Pxx_REQ                  (BIT(6) | BIT(9))
+#define IMX8MM_DDR1_SW_Pxx_REQ                 BIT(5)
+#define IMX8MM_OTG2_SW_Pxx_REQ                 BIT(3)
+#define IMX8MM_OTG1_SW_Pxx_REQ                 BIT(2)
+#define IMX8MM_PCIE_SW_Pxx_REQ                 BIT(1)
+#define IMX8MM_MIPI_SW_Pxx_REQ                 BIT(0)
+
+#define IMX8MN_DISPMIX_SW_Pxx_REQ              BIT(10)
+#define IMX8MN_GPUMIX_SW_Pxx_REQ               BIT(7)
+#define IMX8MN_DDR1_SW_Pxx_REQ         BIT(5)
+#define IMX8MN_OTG1_SW_Pxx_REQ         BIT(2)
+#define IMX8MN_MIPI_SW_Pxx_REQ         BIT(0)
+
+#define IMX8MP_DDRMIX_Pxx_REQ                  BIT(19)
+#define IMX8MP_MEDIA_ISP_DWP_Pxx_REQ           BIT(18)
+#define IMX8MP_HSIOMIX_Pxx_REQ                 BIT(17)
+#define IMX8MP_MIPI_PHY2_Pxx_REQ               BIT(16)
+#define IMX8MP_HDMI_PHY_Pxx_REQ                        BIT(15)
+#define IMX8MP_HDMIMIX_Pxx_REQ                 BIT(14)
+#define IMX8MP_VPU_VC8K_Pxx_REQ                        BIT(13)
+#define IMX8MP_VPU_G2_Pxx_REQ                  BIT(12)
+#define IMX8MP_VPU_G1_Pxx_REQ                  BIT(11)
+#define IMX8MP_MEDIMIX_Pxx_REQ                 BIT(10)
+#define IMX8MP_GPU_3D_Pxx_REQ                  BIT(9)
+#define IMX8MP_VPU_MIX_SHARE_LOGIC_Pxx_REQ     BIT(8)
+#define IMX8MP_GPU_SHARE_LOGIC_Pxx_REQ         BIT(7)
+#define IMX8MP_GPU_2D_Pxx_REQ                  BIT(6)
+#define IMX8MP_AUDIOMIX_Pxx_REQ                        BIT(5)
+#define IMX8MP_MLMIX_Pxx_REQ                   BIT(4)
+#define IMX8MP_USB2_PHY_Pxx_REQ                        BIT(3)
+#define IMX8MP_USB1_PHY_Pxx_REQ                        BIT(2)
+#define IMX8MP_PCIE_PHY_SW_Pxx_REQ             BIT(1)
+#define IMX8MP_MIPI_PHY1_SW_Pxx_REQ            BIT(0)
+
+#define GPC_M4_PU_PDN_FLG              0x1bc
+
+#define IMX8MP_GPC_PU_PWRHSK           0x190
+#define GPC_PU_PWRHSK                  0x1fc
+
+#define IMX8M_GPU_HSK_PWRDNACKN                        BIT(26)
+#define IMX8M_VPU_HSK_PWRDNACKN                        BIT(25)
+#define IMX8M_DISP_HSK_PWRDNACKN               BIT(24)
+#define IMX8M_GPU_HSK_PWRDNREQN                        BIT(6)
+#define IMX8M_VPU_HSK_PWRDNREQN                        BIT(5)
+#define IMX8M_DISP_HSK_PWRDNREQN               BIT(4)
+
+#define IMX8MM_GPUMIX_HSK_PWRDNACKN            BIT(29)
+#define IMX8MM_GPU_HSK_PWRDNACKN               (BIT(27) | BIT(28))
+#define IMX8MM_VPUMIX_HSK_PWRDNACKN            BIT(26)
+#define IMX8MM_DISPMIX_HSK_PWRDNACKN           BIT(25)
+#define IMX8MM_HSIO_HSK_PWRDNACKN              (BIT(23) | BIT(24))
+#define IMX8MM_GPUMIX_HSK_PWRDNREQN            BIT(11)
+#define IMX8MM_GPU_HSK_PWRDNREQN               (BIT(9) | BIT(10))
+#define IMX8MM_VPUMIX_HSK_PWRDNREQN            BIT(8)
+#define IMX8MM_DISPMIX_HSK_PWRDNREQN           BIT(7)
+#define IMX8MM_HSIO_HSK_PWRDNREQN              (BIT(5) | BIT(6))
+
+#define IMX8MN_GPUMIX_HSK_PWRDNACKN            (BIT(29) | BIT(27))
+#define IMX8MN_DISPMIX_HSK_PWRDNACKN           BIT(25)
+#define IMX8MN_HSIO_HSK_PWRDNACKN              BIT(23)
+#define IMX8MN_GPUMIX_HSK_PWRDNREQN            (BIT(11) | BIT(9))
+#define IMX8MN_DISPMIX_HSK_PWRDNREQN           BIT(7)
+#define IMX8MN_HSIO_HSK_PWRDNREQN              BIT(5)
+
+#define IMX8MP_MEDIAMIX_PWRDNACKN              BIT(30)
+#define IMX8MP_HDMIMIX_PWRDNACKN               BIT(29)
+#define IMX8MP_HSIOMIX_PWRDNACKN               BIT(28)
+#define IMX8MP_VPUMIX_PWRDNACKN                        BIT(26)
+#define IMX8MP_GPUMIX_PWRDNACKN                        BIT(25)
+#define IMX8MP_MLMIX_PWRDNACKN                 (BIT(23) | BIT(24))
+#define IMX8MP_AUDIOMIX_PWRDNACKN              (BIT(20) | BIT(31))
+#define IMX8MP_MEDIAMIX_PWRDNREQN              BIT(14)
+#define IMX8MP_HDMIMIX_PWRDNREQN               BIT(13)
+#define IMX8MP_HSIOMIX_PWRDNREQN               BIT(12)
+#define IMX8MP_VPUMIX_PWRDNREQN                        BIT(10)
+#define IMX8MP_GPUMIX_PWRDNREQN                        BIT(9)
+#define IMX8MP_MLMIX_PWRDNREQN                 (BIT(7) | BIT(8))
+#define IMX8MP_AUDIOMIX_PWRDNREQN              (BIT(4) | BIT(15))
+
+/*
+ * The PGC offset values in Reference Manual
+ * (Rev. 1, 01/2018 and the older ones) GPC chapter's
+ * GPC_PGC memory map are incorrect, below offset
+ * values are from design RTL.
+ */
+#define IMX7_PGC_MIPI                  16
+#define IMX7_PGC_PCIE                  17
+#define IMX7_PGC_USB_HSIC              20
+
+#define IMX8M_PGC_MIPI                 16
+#define IMX8M_PGC_PCIE1                        17
+#define IMX8M_PGC_OTG1                 18
+#define IMX8M_PGC_OTG2                 19
+#define IMX8M_PGC_DDR1                 21
+#define IMX8M_PGC_GPU                  23
+#define IMX8M_PGC_VPU                  24
+#define IMX8M_PGC_DISP                 26
+#define IMX8M_PGC_MIPI_CSI1            27
+#define IMX8M_PGC_MIPI_CSI2            28
+#define IMX8M_PGC_PCIE2                        29
+
+#define IMX8MM_PGC_MIPI                        16
+#define IMX8MM_PGC_PCIE                        17
+#define IMX8MM_PGC_OTG1                        18
+#define IMX8MM_PGC_OTG2                        19
+#define IMX8MM_PGC_DDR1                        21
+#define IMX8MM_PGC_GPU2D               22
+#define IMX8MM_PGC_GPUMIX              23
+#define IMX8MM_PGC_VPUMIX              24
+#define IMX8MM_PGC_GPU3D               25
+#define IMX8MM_PGC_DISPMIX             26
+#define IMX8MM_PGC_VPUG1               27
+#define IMX8MM_PGC_VPUG2               28
+#define IMX8MM_PGC_VPUH1               29
+
+#define IMX8MN_PGC_MIPI                16
+#define IMX8MN_PGC_OTG1                18
+#define IMX8MN_PGC_DDR1                21
+#define IMX8MN_PGC_GPUMIX              23
+#define IMX8MN_PGC_DISPMIX             26
+
+#define IMX8MP_PGC_NOC                 9
+#define IMX8MP_PGC_MIPI1               12
+#define IMX8MP_PGC_PCIE                        13
+#define IMX8MP_PGC_USB1                        14
+#define IMX8MP_PGC_USB2                        15
+#define IMX8MP_PGC_MLMIX               16
+#define IMX8MP_PGC_AUDIOMIX            17
+#define IMX8MP_PGC_GPU2D               18
+#define IMX8MP_PGC_GPUMIX              19
+#define IMX8MP_PGC_VPUMIX              20
+#define IMX8MP_PGC_GPU3D               21
+#define IMX8MP_PGC_MEDIAMIX            22
+#define IMX8MP_PGC_VPU_G1              23
+#define IMX8MP_PGC_VPU_G2              24
+#define IMX8MP_PGC_VPU_VC8000E         25
+#define IMX8MP_PGC_HDMIMIX             26
+#define IMX8MP_PGC_HDMI                        27
+#define IMX8MP_PGC_MIPI2               28
+#define IMX8MP_PGC_HSIOMIX             29
+#define IMX8MP_PGC_MEDIA_ISP_DWP       30
+#define IMX8MP_PGC_DDRMIX              31
+
+#define GPC_PGC_CTRL(n)                        (0x800 + (n) * 0x40)
+#define GPC_PGC_SR(n)                  (GPC_PGC_CTRL(n) + 0xc)
+
+#define GPC_PGC_CTRL_PCR               BIT(0)
+
+struct imx_pgc_regs {
+       u16 map;
+       u16 pup;
+       u16 pdn;
+       u16 hsk;
+};
+
+struct imx_pgc_domain {
+       struct generic_pm_domain genpd;
+       struct regmap *regmap;
+       const struct imx_pgc_regs *regs;
+       struct regulator *regulator;
+       struct reset_control *reset;
+       struct clk_bulk_data *clks;
+       int num_clks;
+
+       unsigned long pgc;
+
+       const struct {
+               u32 pxx;
+               u32 map;
+               u32 hskreq;
+               u32 hskack;
+       } bits;
+
+       const int voltage;
+       const bool keep_clocks;
+       struct device *dev;
+
+       unsigned int pgc_sw_pup_reg;
+       unsigned int pgc_sw_pdn_reg;
+};
+
+struct imx_pgc_domain_data {
+       const struct imx_pgc_domain *domains;
+       size_t domains_num;
+       const struct regmap_access_table *reg_access_table;
+       const struct imx_pgc_regs *pgc_regs;
+};
+
+static inline struct imx_pgc_domain *
+to_imx_pgc_domain(struct generic_pm_domain *genpd)
+{
+       return container_of(genpd, struct imx_pgc_domain, genpd);
+}
+
+static int imx_pgc_power_up(struct generic_pm_domain *genpd)
+{
+       struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd);
+       u32 reg_val, pgc;
+       int ret;
+
+       ret = pm_runtime_get_sync(domain->dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(domain->dev);
+               return ret;
+       }
+
+       if (!IS_ERR(domain->regulator)) {
+               ret = regulator_enable(domain->regulator);
+               if (ret) {
+                       dev_err(domain->dev,
+                               "failed to enable regulator: %pe\n",
+                               ERR_PTR(ret));
+                       goto out_put_pm;
+               }
+       }
+
+       reset_control_assert(domain->reset);
+
+       /* Enable reset clocks for all devices in the domain */
+       ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
+       if (ret) {
+               dev_err(domain->dev, "failed to enable reset clocks\n");
+               goto out_regulator_disable;
+       }
+
+       /* delays for reset to propagate */
+       udelay(5);
+
+       if (domain->bits.pxx) {
+               /* request the domain to power up */
+               regmap_update_bits(domain->regmap, domain->regs->pup,
+                                  domain->bits.pxx, domain->bits.pxx);
+               /*
+                * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
+                * for PUP_REQ/PDN_REQ bit to be cleared
+                */
+               ret = regmap_read_poll_timeout(domain->regmap,
+                                              domain->regs->pup, reg_val,
+                                              !(reg_val & domain->bits.pxx),
+                                              0, USEC_PER_MSEC);
+               if (ret) {
+                       dev_err(domain->dev, "failed to command PGC\n");
+                       goto out_clk_disable;
+               }
+
+               /* disable power control */
+               for_each_set_bit(pgc, &domain->pgc, 32) {
+                       regmap_clear_bits(domain->regmap, GPC_PGC_CTRL(pgc),
+                                         GPC_PGC_CTRL_PCR);
+               }
+       }
+
+       /* delay for reset to propagate */
+       udelay(5);
+
+       reset_control_deassert(domain->reset);
+
+       /* request the ADB400 to power up */
+       if (domain->bits.hskreq) {
+               regmap_update_bits(domain->regmap, domain->regs->hsk,
+                                  domain->bits.hskreq, domain->bits.hskreq);
+
+               /*
+                * ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk, reg_val,
+                *                                (reg_val & domain->bits.hskack), 0,
+                *                                USEC_PER_MSEC);
+                * Technically we need the commented code to wait handshake. But that needs
+                * the BLK-CTL module BUS clk-en bit being set.
+                *
+                * There is a separate BLK-CTL module and we will have such a driver for it,
+                * that driver will set the BUS clk-en bit and handshake will be triggered
+                * automatically there. Just add a delay and suppose the handshake finish
+                * after that.
+                */
+       }
+
+       /* Disable reset clocks for all devices in the domain */
+       if (!domain->keep_clocks)
+               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+
+       return 0;
+
+out_clk_disable:
+       clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+out_regulator_disable:
+       if (!IS_ERR(domain->regulator))
+               regulator_disable(domain->regulator);
+out_put_pm:
+       pm_runtime_put(domain->dev);
+
+       return ret;
+}
+
+static int imx_pgc_power_down(struct generic_pm_domain *genpd)
+{
+       struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd);
+       u32 reg_val, pgc;
+       int ret;
+
+       /* Enable reset clocks for all devices in the domain */
+       if (!domain->keep_clocks) {
+               ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
+               if (ret) {
+                       dev_err(domain->dev, "failed to enable reset clocks\n");
+                       return ret;
+               }
+       }
+
+       /* request the ADB400 to power down */
+       if (domain->bits.hskreq) {
+               regmap_clear_bits(domain->regmap, domain->regs->hsk,
+                                 domain->bits.hskreq);
+
+               ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk,
+                                              reg_val,
+                                              !(reg_val & domain->bits.hskack),
+                                              0, USEC_PER_MSEC);
+               if (ret) {
+                       dev_err(domain->dev, "failed to power down ADB400\n");
+                       goto out_clk_disable;
+               }
+       }
+
+       if (domain->bits.pxx) {
+               /* enable power control */
+               for_each_set_bit(pgc, &domain->pgc, 32) {
+                       regmap_update_bits(domain->regmap, GPC_PGC_CTRL(pgc),
+                                          GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
+               }
+
+               /* request the domain to power down */
+               regmap_update_bits(domain->regmap, domain->regs->pdn,
+                                  domain->bits.pxx, domain->bits.pxx);
+               /*
+                * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
+                * for PUP_REQ/PDN_REQ bit to be cleared
+                */
+               ret = regmap_read_poll_timeout(domain->regmap,
+                                              domain->regs->pdn, reg_val,
+                                              !(reg_val & domain->bits.pxx),
+                                              0, USEC_PER_MSEC);
+               if (ret) {
+                       dev_err(domain->dev, "failed to command PGC\n");
+                       goto out_clk_disable;
+               }
+       }
+
+       /* Disable reset clocks for all devices in the domain */
+       clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+
+       if (!IS_ERR(domain->regulator)) {
+               ret = regulator_disable(domain->regulator);
+               if (ret) {
+                       dev_err(domain->dev,
+                               "failed to disable regulator: %pe\n",
+                               ERR_PTR(ret));
+                       return ret;
+               }
+       }
+
+       pm_runtime_put_sync_suspend(domain->dev);
+
+       return 0;
+
+out_clk_disable:
+       if (!domain->keep_clocks)
+               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+
+       return ret;
+}
+
+static const struct imx_pgc_domain imx7_pgc_domains[] = {
+       [IMX7_POWER_DOMAIN_MIPI_PHY] = {
+               .genpd = {
+                       .name      = "mipi-phy",
+               },
+               .bits  = {
+                       .pxx = IMX7_MIPI_PHY_SW_Pxx_REQ,
+                       .map = IMX7_MIPI_PHY_A_CORE_DOMAIN,
+               },
+               .voltage   = 1000000,
+               .pgc       = BIT(IMX7_PGC_MIPI),
+       },
+
+       [IMX7_POWER_DOMAIN_PCIE_PHY] = {
+               .genpd = {
+                       .name      = "pcie-phy",
+               },
+               .bits  = {
+                       .pxx = IMX7_PCIE_PHY_SW_Pxx_REQ,
+                       .map = IMX7_PCIE_PHY_A_CORE_DOMAIN,
+               },
+               .voltage   = 1000000,
+               .pgc       = BIT(IMX7_PGC_PCIE),
+       },
+
+       [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = {
+               .genpd = {
+                       .name      = "usb-hsic-phy",
+               },
+               .bits  = {
+                       .pxx = IMX7_USB_HSIC_PHY_SW_Pxx_REQ,
+                       .map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN,
+               },
+               .voltage   = 1200000,
+               .pgc       = BIT(IMX7_PGC_USB_HSIC),
+       },
+};
+
+static const struct regmap_range imx7_yes_ranges[] = {
+               regmap_reg_range(GPC_LPCR_A_CORE_BSC,
+                                GPC_M4_PU_PDN_FLG),
+               regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_MIPI),
+                                GPC_PGC_SR(IMX7_PGC_MIPI)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_PCIE),
+                                GPC_PGC_SR(IMX7_PGC_PCIE)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_USB_HSIC),
+                                GPC_PGC_SR(IMX7_PGC_USB_HSIC)),
+};
+
+static const struct regmap_access_table imx7_access_table = {
+       .yes_ranges     = imx7_yes_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(imx7_yes_ranges),
+};
+
+static const struct imx_pgc_regs imx7_pgc_regs = {
+       .map = GPC_PGC_CPU_MAPPING,
+       .pup = GPC_PU_PGC_SW_PUP_REQ,
+       .pdn = GPC_PU_PGC_SW_PDN_REQ,
+       .hsk = GPC_PU_PWRHSK,
+};
+
+static const struct imx_pgc_domain_data imx7_pgc_domain_data = {
+       .domains = imx7_pgc_domains,
+       .domains_num = ARRAY_SIZE(imx7_pgc_domains),
+       .reg_access_table = &imx7_access_table,
+       .pgc_regs = &imx7_pgc_regs,
+};
+
+static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+       [IMX8M_POWER_DOMAIN_MIPI] = {
+               .genpd = {
+                       .name      = "mipi",
+               },
+               .bits  = {
+                       .pxx = IMX8M_MIPI_SW_Pxx_REQ,
+                       .map = IMX8M_MIPI_A53_DOMAIN,
+               },
+               .pgc       = BIT(IMX8M_PGC_MIPI),
+       },
+
+       [IMX8M_POWER_DOMAIN_PCIE1] = {
+               .genpd = {
+                       .name = "pcie1",
+               },
+               .bits  = {
+                       .pxx = IMX8M_PCIE1_SW_Pxx_REQ,
+                       .map = IMX8M_PCIE1_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8M_PGC_PCIE1),
+       },
+
+       [IMX8M_POWER_DOMAIN_USB_OTG1] = {
+               .genpd = {
+                       .name = "usb-otg1",
+               },
+               .bits  = {
+                       .pxx = IMX8M_OTG1_SW_Pxx_REQ,
+                       .map = IMX8M_OTG1_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8M_PGC_OTG1),
+       },
+
+       [IMX8M_POWER_DOMAIN_USB_OTG2] = {
+               .genpd = {
+                       .name = "usb-otg2",
+               },
+               .bits  = {
+                       .pxx = IMX8M_OTG2_SW_Pxx_REQ,
+                       .map = IMX8M_OTG2_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8M_PGC_OTG2),
+       },
+
+       [IMX8M_POWER_DOMAIN_DDR1] = {
+               .genpd = {
+                       .name = "ddr1",
+               },
+               .bits  = {
+                       .pxx = IMX8M_DDR1_SW_Pxx_REQ,
+                       .map = IMX8M_DDR2_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8M_PGC_DDR1),
+       },
+
+       [IMX8M_POWER_DOMAIN_GPU] = {
+               .genpd = {
+                       .name = "gpu",
+               },
+               .bits  = {
+                       .pxx = IMX8M_GPU_SW_Pxx_REQ,
+                       .map = IMX8M_GPU_A53_DOMAIN,
+                       .hskreq = IMX8M_GPU_HSK_PWRDNREQN,
+                       .hskack = IMX8M_GPU_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8M_PGC_GPU),
+       },
+
+       [IMX8M_POWER_DOMAIN_VPU] = {
+               .genpd = {
+                       .name = "vpu",
+               },
+               .bits  = {
+                       .pxx = IMX8M_VPU_SW_Pxx_REQ,
+                       .map = IMX8M_VPU_A53_DOMAIN,
+                       .hskreq = IMX8M_VPU_HSK_PWRDNREQN,
+                       .hskack = IMX8M_VPU_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8M_PGC_VPU),
+               .keep_clocks = true,
+       },
+
+       [IMX8M_POWER_DOMAIN_DISP] = {
+               .genpd = {
+                       .name = "disp",
+               },
+               .bits  = {
+                       .pxx = IMX8M_DISP_SW_Pxx_REQ,
+                       .map = IMX8M_DISP_A53_DOMAIN,
+                       .hskreq = IMX8M_DISP_HSK_PWRDNREQN,
+                       .hskack = IMX8M_DISP_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8M_PGC_DISP),
+       },
+
+       [IMX8M_POWER_DOMAIN_MIPI_CSI1] = {
+               .genpd = {
+                       .name = "mipi-csi1",
+               },
+               .bits  = {
+                       .pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ,
+                       .map = IMX8M_MIPI_CSI1_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8M_PGC_MIPI_CSI1),
+       },
+
+       [IMX8M_POWER_DOMAIN_MIPI_CSI2] = {
+               .genpd = {
+                       .name = "mipi-csi2",
+               },
+               .bits  = {
+                       .pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ,
+                       .map = IMX8M_MIPI_CSI2_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8M_PGC_MIPI_CSI2),
+       },
+
+       [IMX8M_POWER_DOMAIN_PCIE2] = {
+               .genpd = {
+                       .name = "pcie2",
+               },
+               .bits  = {
+                       .pxx = IMX8M_PCIE2_SW_Pxx_REQ,
+                       .map = IMX8M_PCIE2_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8M_PGC_PCIE2),
+       },
+};
+
+static const struct regmap_range imx8m_yes_ranges[] = {
+               regmap_reg_range(GPC_LPCR_A_CORE_BSC,
+                                GPC_PU_PWRHSK),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI),
+                                GPC_PGC_SR(IMX8M_PGC_MIPI)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE1),
+                                GPC_PGC_SR(IMX8M_PGC_PCIE1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG1),
+                                GPC_PGC_SR(IMX8M_PGC_OTG1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG2),
+                                GPC_PGC_SR(IMX8M_PGC_OTG2)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DDR1),
+                                GPC_PGC_SR(IMX8M_PGC_DDR1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_GPU),
+                                GPC_PGC_SR(IMX8M_PGC_GPU)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_VPU),
+                                GPC_PGC_SR(IMX8M_PGC_VPU)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DISP),
+                                GPC_PGC_SR(IMX8M_PGC_DISP)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI1),
+                                GPC_PGC_SR(IMX8M_PGC_MIPI_CSI1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI2),
+                                GPC_PGC_SR(IMX8M_PGC_MIPI_CSI2)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE2),
+                                GPC_PGC_SR(IMX8M_PGC_PCIE2)),
+};
+
+static const struct regmap_access_table imx8m_access_table = {
+       .yes_ranges     = imx8m_yes_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(imx8m_yes_ranges),
+};
+
+static const struct imx_pgc_domain_data imx8m_pgc_domain_data = {
+       .domains = imx8m_pgc_domains,
+       .domains_num = ARRAY_SIZE(imx8m_pgc_domains),
+       .reg_access_table = &imx8m_access_table,
+       .pgc_regs = &imx7_pgc_regs,
+};
+
+static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+       [IMX8MM_POWER_DOMAIN_HSIOMIX] = {
+               .genpd = {
+                       .name = "hsiomix",
+               },
+               .bits  = {
+                       .pxx = 0, /* no power sequence control */
+                       .map = 0, /* no power sequence control */
+                       .hskreq = IMX8MM_HSIO_HSK_PWRDNREQN,
+                       .hskack = IMX8MM_HSIO_HSK_PWRDNACKN,
+               },
+               .keep_clocks = true,
+       },
+
+       [IMX8MM_POWER_DOMAIN_PCIE] = {
+               .genpd = {
+                       .name = "pcie",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_PCIE_SW_Pxx_REQ,
+                       .map = IMX8MM_PCIE_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_PCIE),
+       },
+
+       [IMX8MM_POWER_DOMAIN_OTG1] = {
+               .genpd = {
+                       .name = "usb-otg1",
+                       .flags = GENPD_FLAG_ACTIVE_WAKEUP,
+               },
+               .bits  = {
+                       .pxx = IMX8MM_OTG1_SW_Pxx_REQ,
+                       .map = IMX8MM_OTG1_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_OTG1),
+       },
+
+       [IMX8MM_POWER_DOMAIN_OTG2] = {
+               .genpd = {
+                       .name = "usb-otg2",
+                       .flags = GENPD_FLAG_ACTIVE_WAKEUP,
+               },
+               .bits  = {
+                       .pxx = IMX8MM_OTG2_SW_Pxx_REQ,
+                       .map = IMX8MM_OTG2_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_OTG2),
+       },
+
+       [IMX8MM_POWER_DOMAIN_GPUMIX] = {
+               .genpd = {
+                       .name = "gpumix",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_GPUMIX_SW_Pxx_REQ,
+                       .map = IMX8MM_GPUMIX_A53_DOMAIN,
+                       .hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN,
+                       .hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_GPUMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MM_POWER_DOMAIN_GPU] = {
+               .genpd = {
+                       .name = "gpu",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_GPU_SW_Pxx_REQ,
+                       .map = IMX8MM_GPU_A53_DOMAIN,
+                       .hskreq = IMX8MM_GPU_HSK_PWRDNREQN,
+                       .hskack = IMX8MM_GPU_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_GPU2D) | BIT(IMX8MM_PGC_GPU3D),
+       },
+
+       [IMX8MM_POWER_DOMAIN_VPUMIX] = {
+               .genpd = {
+                       .name = "vpumix",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_VPUMIX_SW_Pxx_REQ,
+                       .map = IMX8MM_VPUMIX_A53_DOMAIN,
+                       .hskreq = IMX8MM_VPUMIX_HSK_PWRDNREQN,
+                       .hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_VPUMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MM_POWER_DOMAIN_VPUG1] = {
+               .genpd = {
+                       .name = "vpu-g1",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_VPUG1_SW_Pxx_REQ,
+                       .map = IMX8MM_VPUG1_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_VPUG1),
+       },
+
+       [IMX8MM_POWER_DOMAIN_VPUG2] = {
+               .genpd = {
+                       .name = "vpu-g2",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_VPUG2_SW_Pxx_REQ,
+                       .map = IMX8MM_VPUG2_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_VPUG2),
+       },
+
+       [IMX8MM_POWER_DOMAIN_VPUH1] = {
+               .genpd = {
+                       .name = "vpu-h1",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_VPUH1_SW_Pxx_REQ,
+                       .map = IMX8MM_VPUH1_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_VPUH1),
+               .keep_clocks = true,
+       },
+
+       [IMX8MM_POWER_DOMAIN_DISPMIX] = {
+               .genpd = {
+                       .name = "dispmix",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_DISPMIX_SW_Pxx_REQ,
+                       .map = IMX8MM_DISPMIX_A53_DOMAIN,
+                       .hskreq = IMX8MM_DISPMIX_HSK_PWRDNREQN,
+                       .hskack = IMX8MM_DISPMIX_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_DISPMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MM_POWER_DOMAIN_MIPI] = {
+               .genpd = {
+                       .name = "mipi",
+               },
+               .bits  = {
+                       .pxx = IMX8MM_MIPI_SW_Pxx_REQ,
+                       .map = IMX8MM_MIPI_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_MIPI),
+       },
+};
+
+static const struct regmap_range imx8mm_yes_ranges[] = {
+               regmap_reg_range(GPC_LPCR_A_CORE_BSC,
+                                GPC_PU_PWRHSK),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_MIPI),
+                                GPC_PGC_SR(IMX8MM_PGC_MIPI)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_PCIE),
+                                GPC_PGC_SR(IMX8MM_PGC_PCIE)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_OTG1),
+                                GPC_PGC_SR(IMX8MM_PGC_OTG1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_OTG2),
+                                GPC_PGC_SR(IMX8MM_PGC_OTG2)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_DDR1),
+                                GPC_PGC_SR(IMX8MM_PGC_DDR1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPU2D),
+                                GPC_PGC_SR(IMX8MM_PGC_GPU2D)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPUMIX),
+                                GPC_PGC_SR(IMX8MM_PGC_GPUMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUMIX),
+                                GPC_PGC_SR(IMX8MM_PGC_VPUMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPU3D),
+                                GPC_PGC_SR(IMX8MM_PGC_GPU3D)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_DISPMIX),
+                                GPC_PGC_SR(IMX8MM_PGC_DISPMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUG1),
+                                GPC_PGC_SR(IMX8MM_PGC_VPUG1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUG2),
+                                GPC_PGC_SR(IMX8MM_PGC_VPUG2)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUH1),
+                                GPC_PGC_SR(IMX8MM_PGC_VPUH1)),
+};
+
+static const struct regmap_access_table imx8mm_access_table = {
+       .yes_ranges     = imx8mm_yes_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(imx8mm_yes_ranges),
+};
+
+static const struct imx_pgc_domain_data imx8mm_pgc_domain_data = {
+       .domains = imx8mm_pgc_domains,
+       .domains_num = ARRAY_SIZE(imx8mm_pgc_domains),
+       .reg_access_table = &imx8mm_access_table,
+       .pgc_regs = &imx7_pgc_regs,
+};
+
+static const struct imx_pgc_domain imx8mp_pgc_domains[] = {
+       [IMX8MP_POWER_DOMAIN_MIPI_PHY1] = {
+               .genpd = {
+                       .name = "mipi-phy1",
+               },
+               .bits = {
+                       .pxx = IMX8MP_MIPI_PHY1_SW_Pxx_REQ,
+                       .map = IMX8MP_MIPI_PHY1_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_MIPI1),
+       },
+
+       [IMX8MP_POWER_DOMAIN_PCIE_PHY] = {
+               .genpd = {
+                       .name = "pcie-phy1",
+               },
+               .bits = {
+                       .pxx = IMX8MP_PCIE_PHY_SW_Pxx_REQ,
+                       .map = IMX8MP_PCIE_PHY_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_PCIE),
+       },
+
+       [IMX8MP_POWER_DOMAIN_USB1_PHY] = {
+               .genpd = {
+                       .name = "usb-otg1",
+               },
+               .bits = {
+                       .pxx = IMX8MP_USB1_PHY_Pxx_REQ,
+                       .map = IMX8MP_USB1_PHY_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_USB1),
+       },
+
+       [IMX8MP_POWER_DOMAIN_USB2_PHY] = {
+               .genpd = {
+                       .name = "usb-otg2",
+               },
+               .bits = {
+                       .pxx = IMX8MP_USB2_PHY_Pxx_REQ,
+                       .map = IMX8MP_USB2_PHY_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_USB2),
+       },
+
+       [IMX8MP_POWER_DOMAIN_MLMIX] = {
+               .genpd = {
+                       .name = "mlmix",
+               },
+               .bits = {
+                       .pxx = IMX8MP_MLMIX_Pxx_REQ,
+                       .map = IMX8MP_MLMIX_A53_DOMAIN,
+                       .hskreq = IMX8MP_MLMIX_PWRDNREQN,
+                       .hskack = IMX8MP_MLMIX_PWRDNACKN,
+               },
+               .pgc = BIT(IMX8MP_PGC_MLMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MP_POWER_DOMAIN_AUDIOMIX] = {
+               .genpd = {
+                       .name = "audiomix",
+               },
+               .bits = {
+                       .pxx = IMX8MP_AUDIOMIX_Pxx_REQ,
+                       .map = IMX8MP_AUDIOMIX_A53_DOMAIN,
+                       .hskreq = IMX8MP_AUDIOMIX_PWRDNREQN,
+                       .hskack = IMX8MP_AUDIOMIX_PWRDNACKN,
+               },
+               .pgc = BIT(IMX8MP_PGC_AUDIOMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MP_POWER_DOMAIN_GPU2D] = {
+               .genpd = {
+                       .name = "gpu2d",
+               },
+               .bits = {
+                       .pxx = IMX8MP_GPU_2D_Pxx_REQ,
+                       .map = IMX8MP_GPU2D_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_GPU2D),
+       },
+
+       [IMX8MP_POWER_DOMAIN_GPUMIX] = {
+               .genpd = {
+                       .name = "gpumix",
+               },
+               .bits = {
+                       .pxx = IMX8MP_GPU_SHARE_LOGIC_Pxx_REQ,
+                       .map = IMX8MP_GPUMIX_A53_DOMAIN,
+                       .hskreq = IMX8MP_GPUMIX_PWRDNREQN,
+                       .hskack = IMX8MP_GPUMIX_PWRDNACKN,
+               },
+               .pgc = BIT(IMX8MP_PGC_GPUMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MP_POWER_DOMAIN_VPUMIX] = {
+               .genpd = {
+                       .name = "vpumix",
+               },
+               .bits = {
+                       .pxx = IMX8MP_VPU_MIX_SHARE_LOGIC_Pxx_REQ,
+                       .map = IMX8MP_VPUMIX_A53_DOMAIN,
+                       .hskreq = IMX8MP_VPUMIX_PWRDNREQN,
+                       .hskack = IMX8MP_VPUMIX_PWRDNACKN,
+               },
+               .pgc = BIT(IMX8MP_PGC_VPUMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MP_POWER_DOMAIN_GPU3D] = {
+               .genpd = {
+                       .name = "gpu3d",
+               },
+               .bits = {
+                       .pxx = IMX8MP_GPU_3D_Pxx_REQ,
+                       .map = IMX8MP_GPU3D_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_GPU3D),
+       },
+
+       [IMX8MP_POWER_DOMAIN_MEDIAMIX] = {
+               .genpd = {
+                       .name = "mediamix",
+               },
+               .bits = {
+                       .pxx = IMX8MP_MEDIMIX_Pxx_REQ,
+                       .map = IMX8MP_MEDIAMIX_A53_DOMAIN,
+                       .hskreq = IMX8MP_MEDIAMIX_PWRDNREQN,
+                       .hskack = IMX8MP_MEDIAMIX_PWRDNACKN,
+               },
+               .pgc = BIT(IMX8MP_PGC_MEDIAMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MP_POWER_DOMAIN_VPU_G1] = {
+               .genpd = {
+                       .name = "vpu-g1",
+               },
+               .bits = {
+                       .pxx = IMX8MP_VPU_G1_Pxx_REQ,
+                       .map = IMX8MP_VPU_G1_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_VPU_G1),
+       },
+
+       [IMX8MP_POWER_DOMAIN_VPU_G2] = {
+               .genpd = {
+                       .name = "vpu-g2",
+               },
+               .bits = {
+                       .pxx = IMX8MP_VPU_G2_Pxx_REQ,
+                       .map = IMX8MP_VPU_G2_A53_DOMAIN
+               },
+               .pgc = BIT(IMX8MP_PGC_VPU_G2),
+       },
+
+       [IMX8MP_POWER_DOMAIN_VPU_VC8000E] = {
+               .genpd = {
+                       .name = "vpu-h1",
+               },
+               .bits = {
+                       .pxx = IMX8MP_VPU_VC8K_Pxx_REQ,
+                       .map = IMX8MP_VPU_VC8000E_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_VPU_VC8000E),
+       },
+
+       [IMX8MP_POWER_DOMAIN_HDMIMIX] = {
+               .genpd = {
+                       .name = "hdmimix",
+               },
+               .bits = {
+                       .pxx = IMX8MP_HDMIMIX_Pxx_REQ,
+                       .map = IMX8MP_HDMIMIX_A53_DOMAIN,
+                       .hskreq = IMX8MP_HDMIMIX_PWRDNREQN,
+                       .hskack = IMX8MP_HDMIMIX_PWRDNACKN,
+               },
+               .pgc = BIT(IMX8MP_PGC_HDMIMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MP_POWER_DOMAIN_HDMI_PHY] = {
+               .genpd = {
+                       .name = "hdmi-phy",
+               },
+               .bits = {
+                       .pxx = IMX8MP_HDMI_PHY_Pxx_REQ,
+                       .map = IMX8MP_HDMI_PHY_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_HDMI),
+       },
+
+       [IMX8MP_POWER_DOMAIN_MIPI_PHY2] = {
+               .genpd = {
+                       .name = "mipi-phy2",
+               },
+               .bits = {
+                       .pxx = IMX8MP_MIPI_PHY2_Pxx_REQ,
+                       .map = IMX8MP_MIPI_PHY2_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_MIPI2),
+       },
+
+       [IMX8MP_POWER_DOMAIN_HSIOMIX] = {
+               .genpd = {
+                       .name = "hsiomix",
+               },
+               .bits = {
+                       .pxx = IMX8MP_HSIOMIX_Pxx_REQ,
+                       .map = IMX8MP_HSIOMIX_A53_DOMAIN,
+                       .hskreq = IMX8MP_HSIOMIX_PWRDNREQN,
+                       .hskack = IMX8MP_HSIOMIX_PWRDNACKN,
+               },
+               .pgc = BIT(IMX8MP_PGC_HSIOMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MP_POWER_DOMAIN_MEDIAMIX_ISPDWP] = {
+               .genpd = {
+                       .name = "mediamix-isp-dwp",
+               },
+               .bits = {
+                       .pxx = IMX8MP_MEDIA_ISP_DWP_Pxx_REQ,
+                       .map = IMX8MP_MEDIA_ISPDWP_A53_DOMAIN,
+               },
+               .pgc = BIT(IMX8MP_PGC_MEDIA_ISP_DWP),
+       },
+};
+
+static const struct regmap_range imx8mp_yes_ranges[] = {
+               regmap_reg_range(GPC_LPCR_A_CORE_BSC,
+                                IMX8MP_GPC_PGC_CPU_MAPPING),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_NOC),
+                                GPC_PGC_SR(IMX8MP_PGC_NOC)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MIPI1),
+                                GPC_PGC_SR(IMX8MP_PGC_MIPI1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_PCIE),
+                                GPC_PGC_SR(IMX8MP_PGC_PCIE)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_USB1),
+                                GPC_PGC_SR(IMX8MP_PGC_USB1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_USB2),
+                                GPC_PGC_SR(IMX8MP_PGC_USB2)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MLMIX),
+                                GPC_PGC_SR(IMX8MP_PGC_MLMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_AUDIOMIX),
+                                GPC_PGC_SR(IMX8MP_PGC_AUDIOMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPU2D),
+                                GPC_PGC_SR(IMX8MP_PGC_GPU2D)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPUMIX),
+                                GPC_PGC_SR(IMX8MP_PGC_GPUMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPUMIX),
+                                GPC_PGC_SR(IMX8MP_PGC_VPUMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_GPU3D),
+                                GPC_PGC_SR(IMX8MP_PGC_GPU3D)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MEDIAMIX),
+                                GPC_PGC_SR(IMX8MP_PGC_MEDIAMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_G1),
+                                GPC_PGC_SR(IMX8MP_PGC_VPU_G1)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_G2),
+                                GPC_PGC_SR(IMX8MP_PGC_VPU_G2)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_VPU_VC8000E),
+                                GPC_PGC_SR(IMX8MP_PGC_VPU_VC8000E)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HDMIMIX),
+                                GPC_PGC_SR(IMX8MP_PGC_HDMIMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HDMI),
+                                GPC_PGC_SR(IMX8MP_PGC_HDMI)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MIPI2),
+                                GPC_PGC_SR(IMX8MP_PGC_MIPI2)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_HSIOMIX),
+                                GPC_PGC_SR(IMX8MP_PGC_HSIOMIX)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_MEDIA_ISP_DWP),
+                                GPC_PGC_SR(IMX8MP_PGC_MEDIA_ISP_DWP)),
+               regmap_reg_range(GPC_PGC_CTRL(IMX8MP_PGC_DDRMIX),
+                                GPC_PGC_SR(IMX8MP_PGC_DDRMIX)),
+};
+
+static const struct regmap_access_table imx8mp_access_table = {
+       .yes_ranges     = imx8mp_yes_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(imx8mp_yes_ranges),
+};
+
+static const struct imx_pgc_regs imx8mp_pgc_regs = {
+       .map = IMX8MP_GPC_PGC_CPU_MAPPING,
+       .pup = IMX8MP_GPC_PU_PGC_SW_PUP_REQ,
+       .pdn = IMX8MP_GPC_PU_PGC_SW_PDN_REQ,
+       .hsk = IMX8MP_GPC_PU_PWRHSK,
+};
+static const struct imx_pgc_domain_data imx8mp_pgc_domain_data = {
+       .domains = imx8mp_pgc_domains,
+       .domains_num = ARRAY_SIZE(imx8mp_pgc_domains),
+       .reg_access_table = &imx8mp_access_table,
+       .pgc_regs = &imx8mp_pgc_regs,
+};
+
+static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
+       [IMX8MN_POWER_DOMAIN_HSIOMIX] = {
+               .genpd = {
+                       .name = "hsiomix",
+               },
+               .bits  = {
+                       .pxx = 0, /* no power sequence control */
+                       .map = 0, /* no power sequence control */
+                       .hskreq = IMX8MN_HSIO_HSK_PWRDNREQN,
+                       .hskack = IMX8MN_HSIO_HSK_PWRDNACKN,
+               },
+               .keep_clocks = true,
+       },
+
+       [IMX8MN_POWER_DOMAIN_OTG1] = {
+               .genpd = {
+                       .name = "usb-otg1",
+                       .flags = GENPD_FLAG_ACTIVE_WAKEUP,
+               },
+               .bits  = {
+                       .pxx = IMX8MN_OTG1_SW_Pxx_REQ,
+                       .map = IMX8MN_OTG1_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MN_PGC_OTG1),
+       },
+
+       [IMX8MN_POWER_DOMAIN_GPUMIX] = {
+               .genpd = {
+                       .name = "gpumix",
+               },
+               .bits  = {
+                       .pxx = IMX8MN_GPUMIX_SW_Pxx_REQ,
+                       .map = IMX8MN_GPUMIX_A53_DOMAIN,
+                       .hskreq = IMX8MN_GPUMIX_HSK_PWRDNREQN,
+                       .hskack = IMX8MN_GPUMIX_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8MN_PGC_GPUMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MN_POWER_DOMAIN_DISPMIX] = {
+               .genpd = {
+                       .name = "dispmix",
+               },
+                       .bits  = {
+                       .pxx = IMX8MN_DISPMIX_SW_Pxx_REQ,
+                       .map = IMX8MN_DISPMIX_A53_DOMAIN,
+                       .hskreq = IMX8MN_DISPMIX_HSK_PWRDNREQN,
+                       .hskack = IMX8MN_DISPMIX_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8MN_PGC_DISPMIX),
+               .keep_clocks = true,
+       },
+
+       [IMX8MN_POWER_DOMAIN_MIPI] = {
+               .genpd = {
+                       .name = "mipi",
+               },
+                       .bits  = {
+                       .pxx = IMX8MN_MIPI_SW_Pxx_REQ,
+                       .map = IMX8MN_MIPI_A53_DOMAIN,
+               },
+               .pgc   = BIT(IMX8MN_PGC_MIPI),
+       },
+};
+
+static const struct regmap_range imx8mn_yes_ranges[] = {
+       regmap_reg_range(GPC_LPCR_A_CORE_BSC,
+                        GPC_PU_PWRHSK),
+       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_MIPI),
+                        GPC_PGC_SR(IMX8MN_PGC_MIPI)),
+       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_OTG1),
+                        GPC_PGC_SR(IMX8MN_PGC_OTG1)),
+       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_DDR1),
+                        GPC_PGC_SR(IMX8MN_PGC_DDR1)),
+       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_GPUMIX),
+                        GPC_PGC_SR(IMX8MN_PGC_GPUMIX)),
+       regmap_reg_range(GPC_PGC_CTRL(IMX8MN_PGC_DISPMIX),
+                        GPC_PGC_SR(IMX8MN_PGC_DISPMIX)),
+};
+
+static const struct regmap_access_table imx8mn_access_table = {
+       .yes_ranges     = imx8mn_yes_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(imx8mn_yes_ranges),
+};
+
+static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = {
+       .domains = imx8mn_pgc_domains,
+       .domains_num = ARRAY_SIZE(imx8mn_pgc_domains),
+       .reg_access_table = &imx8mn_access_table,
+       .pgc_regs = &imx7_pgc_regs,
+};
+
+static int imx_pgc_domain_probe(struct platform_device *pdev)
+{
+       struct imx_pgc_domain *domain = pdev->dev.platform_data;
+       int ret;
+
+       domain->dev = &pdev->dev;
+
+       domain->regulator = devm_regulator_get_optional(domain->dev, "power");
+       if (IS_ERR(domain->regulator)) {
+               if (PTR_ERR(domain->regulator) != -ENODEV)
+                       return dev_err_probe(domain->dev, PTR_ERR(domain->regulator),
+                                            "Failed to get domain's regulator\n");
+       } else if (domain->voltage) {
+               regulator_set_voltage(domain->regulator,
+                                     domain->voltage, domain->voltage);
+       }
+
+       domain->num_clks = devm_clk_bulk_get_all(domain->dev, &domain->clks);
+       if (domain->num_clks < 0)
+               return dev_err_probe(domain->dev, domain->num_clks,
+                                    "Failed to get domain's clocks\n");
+
+       domain->reset = devm_reset_control_array_get_optional_exclusive(domain->dev);
+       if (IS_ERR(domain->reset))
+               return dev_err_probe(domain->dev, PTR_ERR(domain->reset),
+                                    "Failed to get domain's resets\n");
+
+       pm_runtime_enable(domain->dev);
+
+       if (domain->bits.map)
+               regmap_update_bits(domain->regmap, domain->regs->map,
+                                  domain->bits.map, domain->bits.map);
+
+       ret = pm_genpd_init(&domain->genpd, NULL, true);
+       if (ret) {
+               dev_err(domain->dev, "Failed to init power domain\n");
+               goto out_domain_unmap;
+       }
+
+       if (IS_ENABLED(CONFIG_LOCKDEP) &&
+           of_property_read_bool(domain->dev->of_node, "power-domains"))
+               lockdep_set_subclass(&domain->genpd.mlock, 1);
+
+       ret = of_genpd_add_provider_simple(domain->dev->of_node,
+                                          &domain->genpd);
+       if (ret) {
+               dev_err(domain->dev, "Failed to add genpd provider\n");
+               goto out_genpd_remove;
+       }
+
+       return 0;
+
+out_genpd_remove:
+       pm_genpd_remove(&domain->genpd);
+out_domain_unmap:
+       if (domain->bits.map)
+               regmap_update_bits(domain->regmap, domain->regs->map,
+                                  domain->bits.map, 0);
+       pm_runtime_disable(domain->dev);
+
+       return ret;
+}
+
+static int imx_pgc_domain_remove(struct platform_device *pdev)
+{
+       struct imx_pgc_domain *domain = pdev->dev.platform_data;
+
+       of_genpd_del_provider(domain->dev->of_node);
+       pm_genpd_remove(&domain->genpd);
+
+       if (domain->bits.map)
+               regmap_update_bits(domain->regmap, domain->regs->map,
+                                  domain->bits.map, 0);
+
+       pm_runtime_disable(domain->dev);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int imx_pgc_domain_suspend(struct device *dev)
+{
+       int ret;
+
+       /*
+        * This may look strange, but is done so the generic PM_SLEEP code
+        * can power down our domain and more importantly power it up again
+        * after resume, without tripping over our usage of runtime PM to
+        * power up/down the nested domains.
+        */
+       ret = pm_runtime_get_sync(dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(dev);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int imx_pgc_domain_resume(struct device *dev)
+{
+       return pm_runtime_put(dev);
+}
+#endif
+
+static const struct dev_pm_ops imx_pgc_domain_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(imx_pgc_domain_suspend, imx_pgc_domain_resume)
+};
+
+static const struct platform_device_id imx_pgc_domain_id[] = {
+       { "imx-pgc-domain", },
+       { },
+};
+
+static struct platform_driver imx_pgc_domain_driver = {
+       .driver = {
+               .name = "imx-pgc",
+               .pm = &imx_pgc_domain_pm_ops,
+       },
+       .probe    = imx_pgc_domain_probe,
+       .remove   = imx_pgc_domain_remove,
+       .id_table = imx_pgc_domain_id,
+};
+builtin_platform_driver(imx_pgc_domain_driver)
+
+static int imx_gpcv2_probe(struct platform_device *pdev)
+{
+       const struct imx_pgc_domain_data *domain_data =
+                       of_device_get_match_data(&pdev->dev);
+
+       struct regmap_config regmap_config = {
+               .reg_bits       = 32,
+               .val_bits       = 32,
+               .reg_stride     = 4,
+               .rd_table       = domain_data->reg_access_table,
+               .wr_table       = domain_data->reg_access_table,
+               .max_register   = SZ_4K,
+       };
+       struct device *dev = &pdev->dev;
+       struct device_node *pgc_np, *np;
+       struct regmap *regmap;
+       void __iomem *base;
+       int ret;
+
+       pgc_np = of_get_child_by_name(dev->of_node, "pgc");
+       if (!pgc_np) {
+               dev_err(dev, "No power domains specified in DT\n");
+               return -EINVAL;
+       }
+
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
+       if (IS_ERR(regmap)) {
+               ret = PTR_ERR(regmap);
+               dev_err(dev, "failed to init regmap (%d)\n", ret);
+               return ret;
+       }
+
+       for_each_child_of_node(pgc_np, np) {
+               struct platform_device *pd_pdev;
+               struct imx_pgc_domain *domain;
+               u32 domain_index;
+
+               if (!of_device_is_available(np))
+                       continue;
+
+               ret = of_property_read_u32(np, "reg", &domain_index);
+               if (ret) {
+                       dev_err(dev, "Failed to read 'reg' property\n");
+                       of_node_put(np);
+                       return ret;
+               }
+
+               if (domain_index >= domain_data->domains_num) {
+                       dev_warn(dev,
+                                "Domain index %d is out of bounds\n",
+                                domain_index);
+                       continue;
+               }
+
+               pd_pdev = platform_device_alloc("imx-pgc-domain",
+                                               domain_index);
+               if (!pd_pdev) {
+                       dev_err(dev, "Failed to allocate platform device\n");
+                       of_node_put(np);
+                       return -ENOMEM;
+               }
+
+               ret = platform_device_add_data(pd_pdev,
+                                              &domain_data->domains[domain_index],
+                                              sizeof(domain_data->domains[domain_index]));
+               if (ret) {
+                       platform_device_put(pd_pdev);
+                       of_node_put(np);
+                       return ret;
+               }
+
+               domain = pd_pdev->dev.platform_data;
+               domain->regmap = regmap;
+               domain->regs = domain_data->pgc_regs;
+
+               domain->genpd.power_on  = imx_pgc_power_up;
+               domain->genpd.power_off = imx_pgc_power_down;
+
+               pd_pdev->dev.parent = dev;
+               device_set_node(&pd_pdev->dev, of_fwnode_handle(np));
+
+               ret = platform_device_add(pd_pdev);
+               if (ret) {
+                       platform_device_put(pd_pdev);
+                       of_node_put(np);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static const struct of_device_id imx_gpcv2_dt_ids[] = {
+       { .compatible = "fsl,imx7d-gpc", .data = &imx7_pgc_domain_data, },
+       { .compatible = "fsl,imx8mm-gpc", .data = &imx8mm_pgc_domain_data, },
+       { .compatible = "fsl,imx8mn-gpc", .data = &imx8mn_pgc_domain_data, },
+       { .compatible = "fsl,imx8mp-gpc", .data = &imx8mp_pgc_domain_data, },
+       { .compatible = "fsl,imx8mq-gpc", .data = &imx8m_pgc_domain_data, },
+       { }
+};
+
+static struct platform_driver imx_gpc_driver = {
+       .driver = {
+               .name = "imx-gpcv2",
+               .of_match_table = imx_gpcv2_dt_ids,
+       },
+       .probe = imx_gpcv2_probe,
+};
+builtin_platform_driver(imx_gpc_driver)
diff --git a/drivers/pmdomain/imx/imx8m-blk-ctrl.c b/drivers/pmdomain/imx/imx8m-blk-ctrl.c
new file mode 100644 (file)
index 0000000..cc5ef6e
--- /dev/null
@@ -0,0 +1,899 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Copyright 2021 Pengutronix, Lucas Stach <kernel@pengutronix.de>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/device.h>
+#include <linux/interconnect.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/clk.h>
+
+#include <dt-bindings/power/imx8mm-power.h>
+#include <dt-bindings/power/imx8mn-power.h>
+#include <dt-bindings/power/imx8mp-power.h>
+#include <dt-bindings/power/imx8mq-power.h>
+
+#define BLK_SFT_RSTN   0x0
+#define BLK_CLK_EN     0x4
+#define BLK_MIPI_RESET_DIV     0x8 /* Mini/Nano/Plus DISPLAY_BLK_CTRL only */
+
+struct imx8m_blk_ctrl_domain;
+
+struct imx8m_blk_ctrl {
+       struct device *dev;
+       struct notifier_block power_nb;
+       struct device *bus_power_dev;
+       struct regmap *regmap;
+       struct imx8m_blk_ctrl_domain *domains;
+       struct genpd_onecell_data onecell_data;
+};
+
+struct imx8m_blk_ctrl_domain_data {
+       const char *name;
+       const char * const *clk_names;
+       const char * const *path_names;
+       const char *gpc_name;
+       int num_clks;
+       int num_paths;
+       u32 rst_mask;
+       u32 clk_mask;
+
+       /*
+        * i.MX8M Mini, Nano and Plus have a third DISPLAY_BLK_CTRL register
+        * which is used to control the reset for the MIPI Phy.
+        * Since it's only present in certain circumstances,
+        * an if-statement should be used before setting and clearing this
+        * register.
+        */
+       u32 mipi_phy_rst_mask;
+};
+
+#define DOMAIN_MAX_CLKS 4
+#define DOMAIN_MAX_PATHS 4
+
+struct imx8m_blk_ctrl_domain {
+       struct generic_pm_domain genpd;
+       const struct imx8m_blk_ctrl_domain_data *data;
+       struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
+       struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
+       struct device *power_dev;
+       struct imx8m_blk_ctrl *bc;
+       int num_paths;
+};
+
+struct imx8m_blk_ctrl_data {
+       int max_reg;
+       notifier_fn_t power_notifier_fn;
+       const struct imx8m_blk_ctrl_domain_data *domains;
+       int num_domains;
+};
+
+static inline struct imx8m_blk_ctrl_domain *
+to_imx8m_blk_ctrl_domain(struct generic_pm_domain *genpd)
+{
+       return container_of(genpd, struct imx8m_blk_ctrl_domain, genpd);
+}
+
+static int imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd)
+{
+       struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
+       const struct imx8m_blk_ctrl_domain_data *data = domain->data;
+       struct imx8m_blk_ctrl *bc = domain->bc;
+       int ret;
+
+       /* make sure bus domain is awake */
+       ret = pm_runtime_get_sync(bc->bus_power_dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(bc->bus_power_dev);
+               dev_err(bc->dev, "failed to power up bus domain\n");
+               return ret;
+       }
+
+       /* put devices into reset */
+       regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
+       if (data->mipi_phy_rst_mask)
+               regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
+
+       /* enable upstream and blk-ctrl clocks to allow reset to propagate */
+       ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
+       if (ret) {
+               dev_err(bc->dev, "failed to enable clocks\n");
+               goto bus_put;
+       }
+       regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
+
+       /* power up upstream GPC domain */
+       ret = pm_runtime_get_sync(domain->power_dev);
+       if (ret < 0) {
+               dev_err(bc->dev, "failed to power up peripheral domain\n");
+               goto clk_disable;
+       }
+
+       /* wait for reset to propagate */
+       udelay(5);
+
+       /* release reset */
+       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
+       if (data->mipi_phy_rst_mask)
+               regmap_set_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
+
+       ret = icc_bulk_set_bw(domain->num_paths, domain->paths);
+       if (ret)
+               dev_err(bc->dev, "failed to set icc bw\n");
+
+       /* disable upstream clocks */
+       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+
+       return 0;
+
+clk_disable:
+       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+bus_put:
+       pm_runtime_put(bc->bus_power_dev);
+
+       return ret;
+}
+
+static int imx8m_blk_ctrl_power_off(struct generic_pm_domain *genpd)
+{
+       struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
+       const struct imx8m_blk_ctrl_domain_data *data = domain->data;
+       struct imx8m_blk_ctrl *bc = domain->bc;
+
+       /* put devices into reset and disable clocks */
+       if (data->mipi_phy_rst_mask)
+               regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
+
+       regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
+       regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
+
+       /* power down upstream GPC domain */
+       pm_runtime_put(domain->power_dev);
+
+       /* allow bus domain to suspend */
+       pm_runtime_put(bc->bus_power_dev);
+
+       return 0;
+}
+
+static struct lock_class_key blk_ctrl_genpd_lock_class;
+
+static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
+{
+       const struct imx8m_blk_ctrl_data *bc_data;
+       struct device *dev = &pdev->dev;
+       struct imx8m_blk_ctrl *bc;
+       void __iomem *base;
+       int i, ret;
+
+       struct regmap_config regmap_config = {
+               .reg_bits       = 32,
+               .val_bits       = 32,
+               .reg_stride     = 4,
+       };
+
+       bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
+       if (!bc)
+               return -ENOMEM;
+
+       bc->dev = dev;
+
+       bc_data = of_device_get_match_data(dev);
+
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       regmap_config.max_register = bc_data->max_reg;
+       bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
+       if (IS_ERR(bc->regmap))
+               return dev_err_probe(dev, PTR_ERR(bc->regmap),
+                                    "failed to init regmap\n");
+
+       bc->domains = devm_kcalloc(dev, bc_data->num_domains,
+                                  sizeof(struct imx8m_blk_ctrl_domain),
+                                  GFP_KERNEL);
+       if (!bc->domains)
+               return -ENOMEM;
+
+       bc->onecell_data.num_domains = bc_data->num_domains;
+       bc->onecell_data.domains =
+               devm_kcalloc(dev, bc_data->num_domains,
+                            sizeof(struct generic_pm_domain *), GFP_KERNEL);
+       if (!bc->onecell_data.domains)
+               return -ENOMEM;
+
+       bc->bus_power_dev = dev_pm_domain_attach_by_name(dev, "bus");
+       if (IS_ERR(bc->bus_power_dev)) {
+               if (PTR_ERR(bc->bus_power_dev) == -ENODEV)
+                       return dev_err_probe(dev, -EPROBE_DEFER,
+                                            "failed to attach power domain \"bus\"\n");
+               else
+                       return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
+                                            "failed to attach power domain \"bus\"\n");
+       }
+
+       for (i = 0; i < bc_data->num_domains; i++) {
+               const struct imx8m_blk_ctrl_domain_data *data = &bc_data->domains[i];
+               struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
+               int j;
+
+               domain->data = data;
+               domain->num_paths = data->num_paths;
+
+               for (j = 0; j < data->num_clks; j++)
+                       domain->clks[j].id = data->clk_names[j];
+
+               for (j = 0; j < data->num_paths; j++) {
+                       domain->paths[j].name = data->path_names[j];
+                       /* Fake value for now, just let ICC could configure NoC mode/priority */
+                       domain->paths[j].avg_bw = 1;
+                       domain->paths[j].peak_bw = 1;
+               }
+
+               ret = devm_of_icc_bulk_get(dev, data->num_paths, domain->paths);
+               if (ret) {
+                       if (ret != -EPROBE_DEFER) {
+                               dev_warn_once(dev, "Could not get interconnect paths, NoC will stay unconfigured!\n");
+                               domain->num_paths = 0;
+                       } else {
+                               dev_err_probe(dev, ret, "failed to get noc entries\n");
+                               goto cleanup_pds;
+                       }
+               }
+
+               ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
+               if (ret) {
+                       dev_err_probe(dev, ret, "failed to get clock\n");
+                       goto cleanup_pds;
+               }
+
+               domain->power_dev =
+                       dev_pm_domain_attach_by_name(dev, data->gpc_name);
+               if (IS_ERR(domain->power_dev)) {
+                       dev_err_probe(dev, PTR_ERR(domain->power_dev),
+                                     "failed to attach power domain \"%s\"\n",
+                                     data->gpc_name);
+                       ret = PTR_ERR(domain->power_dev);
+                       goto cleanup_pds;
+               }
+
+               domain->genpd.name = data->name;
+               domain->genpd.power_on = imx8m_blk_ctrl_power_on;
+               domain->genpd.power_off = imx8m_blk_ctrl_power_off;
+               domain->bc = bc;
+
+               ret = pm_genpd_init(&domain->genpd, NULL, true);
+               if (ret) {
+                       dev_err_probe(dev, ret,
+                                     "failed to init power domain \"%s\"\n",
+                                     data->gpc_name);
+                       dev_pm_domain_detach(domain->power_dev, true);
+                       goto cleanup_pds;
+               }
+
+               /*
+                * We use runtime PM to trigger power on/off of the upstream GPC
+                * domain, as a strict hierarchical parent/child power domain
+                * setup doesn't allow us to meet the sequencing requirements.
+                * This means we have nested locking of genpd locks, without the
+                * nesting being visible at the genpd level, so we need a
+                * separate lock class to make lockdep aware of the fact that
+                * this are separate domain locks that can be nested without a
+                * self-deadlock.
+                */
+               lockdep_set_class(&domain->genpd.mlock,
+                                 &blk_ctrl_genpd_lock_class);
+
+               bc->onecell_data.domains[i] = &domain->genpd;
+       }
+
+       ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
+       if (ret) {
+               dev_err_probe(dev, ret, "failed to add power domain provider\n");
+               goto cleanup_pds;
+       }
+
+       bc->power_nb.notifier_call = bc_data->power_notifier_fn;
+       ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb);
+       if (ret) {
+               dev_err_probe(dev, ret, "failed to add power notifier\n");
+               goto cleanup_provider;
+       }
+
+       dev_set_drvdata(dev, bc);
+
+       ret = devm_of_platform_populate(dev);
+       if (ret)
+               goto cleanup_provider;
+
+       return 0;
+
+cleanup_provider:
+       of_genpd_del_provider(dev->of_node);
+cleanup_pds:
+       for (i--; i >= 0; i--) {
+               pm_genpd_remove(&bc->domains[i].genpd);
+               dev_pm_domain_detach(bc->domains[i].power_dev, true);
+       }
+
+       dev_pm_domain_detach(bc->bus_power_dev, true);
+
+       return ret;
+}
+
+static int imx8m_blk_ctrl_remove(struct platform_device *pdev)
+{
+       struct imx8m_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
+       int i;
+
+       of_genpd_del_provider(pdev->dev.of_node);
+
+       for (i = 0; bc->onecell_data.num_domains; i++) {
+               struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
+
+               pm_genpd_remove(&domain->genpd);
+               dev_pm_domain_detach(domain->power_dev, true);
+       }
+
+       dev_pm_genpd_remove_notifier(bc->bus_power_dev);
+
+       dev_pm_domain_detach(bc->bus_power_dev, true);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int imx8m_blk_ctrl_suspend(struct device *dev)
+{
+       struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
+       int ret, i;
+
+       /*
+        * This may look strange, but is done so the generic PM_SLEEP code
+        * can power down our domains and more importantly power them up again
+        * after resume, without tripping over our usage of runtime PM to
+        * control the upstream GPC domains. Things happen in the right order
+        * in the system suspend/resume paths due to the device parent/child
+        * hierarchy.
+        */
+       ret = pm_runtime_get_sync(bc->bus_power_dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(bc->bus_power_dev);
+               return ret;
+       }
+
+       for (i = 0; i < bc->onecell_data.num_domains; i++) {
+               struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
+
+               ret = pm_runtime_get_sync(domain->power_dev);
+               if (ret < 0) {
+                       pm_runtime_put_noidle(domain->power_dev);
+                       goto out_fail;
+               }
+       }
+
+       return 0;
+
+out_fail:
+       for (i--; i >= 0; i--)
+               pm_runtime_put(bc->domains[i].power_dev);
+
+       pm_runtime_put(bc->bus_power_dev);
+
+       return ret;
+}
+
+static int imx8m_blk_ctrl_resume(struct device *dev)
+{
+       struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
+       int i;
+
+       for (i = 0; i < bc->onecell_data.num_domains; i++)
+               pm_runtime_put(bc->domains[i].power_dev);
+
+       pm_runtime_put(bc->bus_power_dev);
+
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops imx8m_blk_ctrl_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(imx8m_blk_ctrl_suspend, imx8m_blk_ctrl_resume)
+};
+
+static int imx8mm_vpu_power_notifier(struct notifier_block *nb,
+                                    unsigned long action, void *data)
+{
+       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
+                                                power_nb);
+
+       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
+               return NOTIFY_OK;
+
+       /*
+        * The ADB in the VPUMIX domain has no separate reset and clock
+        * enable bits, but is ungated together with the VPU clocks. To
+        * allow the handshake with the GPC to progress we put the VPUs
+        * in reset and ungate the clocks.
+        */
+       regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1) | BIT(2));
+       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1) | BIT(2));
+
+       if (action == GENPD_NOTIFY_ON) {
+               /*
+                * On power up we have no software backchannel to the GPC to
+                * wait for the ADB handshake to happen, so we just delay for a
+                * bit. On power down the GPC driver waits for the handshake.
+                */
+               udelay(5);
+
+               /* set "fuse" bits to enable the VPUs */
+               regmap_set_bits(bc->regmap, 0x8, 0xffffffff);
+               regmap_set_bits(bc->regmap, 0xc, 0xffffffff);
+               regmap_set_bits(bc->regmap, 0x10, 0xffffffff);
+               regmap_set_bits(bc->regmap, 0x14, 0xffffffff);
+       }
+
+       return NOTIFY_OK;
+}
+
+static const struct imx8m_blk_ctrl_domain_data imx8mm_vpu_blk_ctl_domain_data[] = {
+       [IMX8MM_VPUBLK_PD_G1] = {
+               .name = "vpublk-g1",
+               .clk_names = (const char *[]){ "g1", },
+               .num_clks = 1,
+               .gpc_name = "g1",
+               .rst_mask = BIT(1),
+               .clk_mask = BIT(1),
+       },
+       [IMX8MM_VPUBLK_PD_G2] = {
+               .name = "vpublk-g2",
+               .clk_names = (const char *[]){ "g2", },
+               .num_clks = 1,
+               .gpc_name = "g2",
+               .rst_mask = BIT(0),
+               .clk_mask = BIT(0),
+       },
+       [IMX8MM_VPUBLK_PD_H1] = {
+               .name = "vpublk-h1",
+               .clk_names = (const char *[]){ "h1", },
+               .num_clks = 1,
+               .gpc_name = "h1",
+               .rst_mask = BIT(2),
+               .clk_mask = BIT(2),
+       },
+};
+
+static const struct imx8m_blk_ctrl_data imx8mm_vpu_blk_ctl_dev_data = {
+       .max_reg = 0x18,
+       .power_notifier_fn = imx8mm_vpu_power_notifier,
+       .domains = imx8mm_vpu_blk_ctl_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mm_vpu_blk_ctl_domain_data),
+};
+
+static const struct imx8m_blk_ctrl_domain_data imx8mp_vpu_blk_ctl_domain_data[] = {
+       [IMX8MP_VPUBLK_PD_G1] = {
+               .name = "vpublk-g1",
+               .clk_names = (const char *[]){ "g1", },
+               .num_clks = 1,
+               .gpc_name = "g1",
+               .rst_mask = BIT(1),
+               .clk_mask = BIT(1),
+               .path_names = (const char *[]){"g1"},
+               .num_paths = 1,
+       },
+       [IMX8MP_VPUBLK_PD_G2] = {
+               .name = "vpublk-g2",
+               .clk_names = (const char *[]){ "g2", },
+               .num_clks = 1,
+               .gpc_name = "g2",
+               .rst_mask = BIT(0),
+               .clk_mask = BIT(0),
+               .path_names = (const char *[]){"g2"},
+               .num_paths = 1,
+       },
+       [IMX8MP_VPUBLK_PD_VC8000E] = {
+               .name = "vpublk-vc8000e",
+               .clk_names = (const char *[]){ "vc8000e", },
+               .num_clks = 1,
+               .gpc_name = "vc8000e",
+               .rst_mask = BIT(2),
+               .clk_mask = BIT(2),
+               .path_names = (const char *[]){"vc8000e"},
+               .num_paths = 1,
+       },
+};
+
+static const struct imx8m_blk_ctrl_data imx8mp_vpu_blk_ctl_dev_data = {
+       .max_reg = 0x18,
+       .power_notifier_fn = imx8mm_vpu_power_notifier,
+       .domains = imx8mp_vpu_blk_ctl_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mp_vpu_blk_ctl_domain_data),
+};
+
+static int imx8mm_disp_power_notifier(struct notifier_block *nb,
+                                     unsigned long action, void *data)
+{
+       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
+                                                power_nb);
+
+       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
+               return NOTIFY_OK;
+
+       /* Enable bus clock and deassert bus reset */
+       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(12));
+       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(6));
+
+       /*
+        * On power up we have no software backchannel to the GPC to
+        * wait for the ADB handshake to happen, so we just delay for a
+        * bit. On power down the GPC driver waits for the handshake.
+        */
+       if (action == GENPD_NOTIFY_ON)
+               udelay(5);
+
+
+       return NOTIFY_OK;
+}
+
+static const struct imx8m_blk_ctrl_domain_data imx8mm_disp_blk_ctl_domain_data[] = {
+       [IMX8MM_DISPBLK_PD_CSI_BRIDGE] = {
+               .name = "dispblk-csi-bridge",
+               .clk_names = (const char *[]){ "csi-bridge-axi", "csi-bridge-apb",
+                                              "csi-bridge-core", },
+               .num_clks = 3,
+               .gpc_name = "csi-bridge",
+               .rst_mask = BIT(0) | BIT(1) | BIT(2),
+               .clk_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5),
+       },
+       [IMX8MM_DISPBLK_PD_LCDIF] = {
+               .name = "dispblk-lcdif",
+               .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
+               .num_clks = 3,
+               .gpc_name = "lcdif",
+               .clk_mask = BIT(6) | BIT(7),
+       },
+       [IMX8MM_DISPBLK_PD_MIPI_DSI] = {
+               .name = "dispblk-mipi-dsi",
+               .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
+               .num_clks = 2,
+               .gpc_name = "mipi-dsi",
+               .rst_mask = BIT(5),
+               .clk_mask = BIT(8) | BIT(9),
+               .mipi_phy_rst_mask = BIT(17),
+       },
+       [IMX8MM_DISPBLK_PD_MIPI_CSI] = {
+               .name = "dispblk-mipi-csi",
+               .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
+               .num_clks = 2,
+               .gpc_name = "mipi-csi",
+               .rst_mask = BIT(3) | BIT(4),
+               .clk_mask = BIT(10) | BIT(11),
+               .mipi_phy_rst_mask = BIT(16),
+       },
+};
+
+static const struct imx8m_blk_ctrl_data imx8mm_disp_blk_ctl_dev_data = {
+       .max_reg = 0x2c,
+       .power_notifier_fn = imx8mm_disp_power_notifier,
+       .domains = imx8mm_disp_blk_ctl_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mm_disp_blk_ctl_domain_data),
+};
+
+
+static int imx8mn_disp_power_notifier(struct notifier_block *nb,
+                                     unsigned long action, void *data)
+{
+       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
+                                                power_nb);
+
+       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
+               return NOTIFY_OK;
+
+       /* Enable bus clock and deassert bus reset */
+       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8));
+       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8));
+
+       /*
+        * On power up we have no software backchannel to the GPC to
+        * wait for the ADB handshake to happen, so we just delay for a
+        * bit. On power down the GPC driver waits for the handshake.
+        */
+       if (action == GENPD_NOTIFY_ON)
+               udelay(5);
+
+
+       return NOTIFY_OK;
+}
+
+static const struct imx8m_blk_ctrl_domain_data imx8mn_disp_blk_ctl_domain_data[] = {
+       [IMX8MN_DISPBLK_PD_MIPI_DSI] = {
+               .name = "dispblk-mipi-dsi",
+               .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
+               .num_clks = 2,
+               .gpc_name = "mipi-dsi",
+               .rst_mask = BIT(0) | BIT(1),
+               .clk_mask = BIT(0) | BIT(1),
+               .mipi_phy_rst_mask = BIT(17),
+       },
+       [IMX8MN_DISPBLK_PD_MIPI_CSI] = {
+               .name = "dispblk-mipi-csi",
+               .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
+               .num_clks = 2,
+               .gpc_name = "mipi-csi",
+               .rst_mask = BIT(2) | BIT(3),
+               .clk_mask = BIT(2) | BIT(3),
+               .mipi_phy_rst_mask = BIT(16),
+       },
+       [IMX8MN_DISPBLK_PD_LCDIF] = {
+               .name = "dispblk-lcdif",
+               .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
+               .num_clks = 3,
+               .gpc_name = "lcdif",
+               .rst_mask = BIT(4) | BIT(5),
+               .clk_mask = BIT(4) | BIT(5),
+       },
+       [IMX8MN_DISPBLK_PD_ISI] = {
+               .name = "dispblk-isi",
+               .clk_names = (const char *[]){ "disp_axi", "disp_apb", "disp_axi_root",
+                                               "disp_apb_root"},
+               .num_clks = 4,
+               .gpc_name = "isi",
+               .rst_mask = BIT(6) | BIT(7),
+               .clk_mask = BIT(6) | BIT(7),
+       },
+};
+
+static const struct imx8m_blk_ctrl_data imx8mn_disp_blk_ctl_dev_data = {
+       .max_reg = 0x84,
+       .power_notifier_fn = imx8mn_disp_power_notifier,
+       .domains = imx8mn_disp_blk_ctl_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mn_disp_blk_ctl_domain_data),
+};
+
+#define LCDIF_ARCACHE_CTRL     0x4c
+#define  LCDIF_1_RD_HURRY      GENMASK(15, 13)
+#define  LCDIF_0_RD_HURRY      GENMASK(12, 10)
+
+static int imx8mp_media_power_notifier(struct notifier_block *nb,
+                               unsigned long action, void *data)
+{
+       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
+                                                power_nb);
+
+       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
+               return NOTIFY_OK;
+
+       /* Enable bus clock and deassert bus reset */
+       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8));
+       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8));
+
+       if (action == GENPD_NOTIFY_ON) {
+               /*
+                * On power up we have no software backchannel to the GPC to
+                * wait for the ADB handshake to happen, so we just delay for a
+                * bit. On power down the GPC driver waits for the handshake.
+                */
+               udelay(5);
+
+               /*
+                * Set panic read hurry level for both LCDIF interfaces to
+                * maximum priority to minimize chances of display FIFO
+                * underflow.
+                */
+               regmap_set_bits(bc->regmap, LCDIF_ARCACHE_CTRL,
+                               FIELD_PREP(LCDIF_1_RD_HURRY, 7) |
+                               FIELD_PREP(LCDIF_0_RD_HURRY, 7));
+       }
+
+       return NOTIFY_OK;
+}
+
+/*
+ * From i.MX 8M Plus Applications Processor Reference Manual, Rev. 1,
+ * section 13.2.2, 13.2.3
+ * isp-ahb and dwe are not in Figure 13-5. Media BLK_CTRL Clocks
+ */
+static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[] = {
+       [IMX8MP_MEDIABLK_PD_MIPI_DSI_1] = {
+               .name = "mediablk-mipi-dsi-1",
+               .clk_names = (const char *[]){ "apb", "phy", },
+               .num_clks = 2,
+               .gpc_name = "mipi-dsi1",
+               .rst_mask = BIT(0) | BIT(1),
+               .clk_mask = BIT(0) | BIT(1),
+               .mipi_phy_rst_mask = BIT(17),
+       },
+       [IMX8MP_MEDIABLK_PD_MIPI_CSI2_1] = {
+               .name = "mediablk-mipi-csi2-1",
+               .clk_names = (const char *[]){ "apb", "cam1" },
+               .num_clks = 2,
+               .gpc_name = "mipi-csi1",
+               .rst_mask = BIT(2) | BIT(3),
+               .clk_mask = BIT(2) | BIT(3),
+               .mipi_phy_rst_mask = BIT(16),
+       },
+       [IMX8MP_MEDIABLK_PD_LCDIF_1] = {
+               .name = "mediablk-lcdif-1",
+               .clk_names = (const char *[]){ "disp1", "apb", "axi", },
+               .num_clks = 3,
+               .gpc_name = "lcdif1",
+               .rst_mask = BIT(4) | BIT(5) | BIT(23),
+               .clk_mask = BIT(4) | BIT(5) | BIT(23),
+               .path_names = (const char *[]){"lcdif-rd", "lcdif-wr"},
+               .num_paths = 2,
+       },
+       [IMX8MP_MEDIABLK_PD_ISI] = {
+               .name = "mediablk-isi",
+               .clk_names = (const char *[]){ "axi", "apb" },
+               .num_clks = 2,
+               .gpc_name = "isi",
+               .rst_mask = BIT(6) | BIT(7),
+               .clk_mask = BIT(6) | BIT(7),
+               .path_names = (const char *[]){"isi0", "isi1", "isi2"},
+               .num_paths = 3,
+       },
+       [IMX8MP_MEDIABLK_PD_MIPI_CSI2_2] = {
+               .name = "mediablk-mipi-csi2-2",
+               .clk_names = (const char *[]){ "apb", "cam2" },
+               .num_clks = 2,
+               .gpc_name = "mipi-csi2",
+               .rst_mask = BIT(9) | BIT(10),
+               .clk_mask = BIT(9) | BIT(10),
+               .mipi_phy_rst_mask = BIT(30),
+       },
+       [IMX8MP_MEDIABLK_PD_LCDIF_2] = {
+               .name = "mediablk-lcdif-2",
+               .clk_names = (const char *[]){ "disp2", "apb", "axi", },
+               .num_clks = 3,
+               .gpc_name = "lcdif2",
+               .rst_mask = BIT(11) | BIT(12) | BIT(24),
+               .clk_mask = BIT(11) | BIT(12) | BIT(24),
+               .path_names = (const char *[]){"lcdif-rd", "lcdif-wr"},
+               .num_paths = 2,
+       },
+       [IMX8MP_MEDIABLK_PD_ISP] = {
+               .name = "mediablk-isp",
+               .clk_names = (const char *[]){ "isp", "axi", "apb" },
+               .num_clks = 3,
+               .gpc_name = "isp",
+               .rst_mask = BIT(16) | BIT(17) | BIT(18),
+               .clk_mask = BIT(16) | BIT(17) | BIT(18),
+               .path_names = (const char *[]){"isp0", "isp1"},
+               .num_paths = 2,
+       },
+       [IMX8MP_MEDIABLK_PD_DWE] = {
+               .name = "mediablk-dwe",
+               .clk_names = (const char *[]){ "axi", "apb" },
+               .num_clks = 2,
+               .gpc_name = "dwe",
+               .rst_mask = BIT(19) | BIT(20) | BIT(21),
+               .clk_mask = BIT(19) | BIT(20) | BIT(21),
+               .path_names = (const char *[]){"dwe"},
+               .num_paths = 1,
+       },
+       [IMX8MP_MEDIABLK_PD_MIPI_DSI_2] = {
+               .name = "mediablk-mipi-dsi-2",
+               .clk_names = (const char *[]){ "phy", },
+               .num_clks = 1,
+               .gpc_name = "mipi-dsi2",
+               .rst_mask = BIT(22),
+               .clk_mask = BIT(22),
+               .mipi_phy_rst_mask = BIT(29),
+       },
+};
+
+static const struct imx8m_blk_ctrl_data imx8mp_media_blk_ctl_dev_data = {
+       .max_reg = 0x138,
+       .power_notifier_fn = imx8mp_media_power_notifier,
+       .domains = imx8mp_media_blk_ctl_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mp_media_blk_ctl_domain_data),
+};
+
+static int imx8mq_vpu_power_notifier(struct notifier_block *nb,
+                                    unsigned long action, void *data)
+{
+       struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
+                                                power_nb);
+
+       if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
+               return NOTIFY_OK;
+
+       /*
+        * The ADB in the VPUMIX domain has no separate reset and clock
+        * enable bits, but is ungated and reset together with the VPUs. The
+        * reset and clock enable inputs to the ADB is a logical OR of the
+        * VPU bits. In order to set the G2 fuse bits, the G2 clock must
+        * also be enabled.
+        */
+       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1));
+       regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1));
+
+       if (action == GENPD_NOTIFY_ON) {
+               /*
+                * On power up we have no software backchannel to the GPC to
+                * wait for the ADB handshake to happen, so we just delay for a
+                * bit. On power down the GPC driver waits for the handshake.
+                */
+               udelay(5);
+
+               /* set "fuse" bits to enable the VPUs */
+               regmap_set_bits(bc->regmap, 0x8, 0xffffffff);
+               regmap_set_bits(bc->regmap, 0xc, 0xffffffff);
+               regmap_set_bits(bc->regmap, 0x10, 0xffffffff);
+       }
+
+       return NOTIFY_OK;
+}
+
+static const struct imx8m_blk_ctrl_domain_data imx8mq_vpu_blk_ctl_domain_data[] = {
+       [IMX8MQ_VPUBLK_PD_G1] = {
+               .name = "vpublk-g1",
+               .clk_names = (const char *[]){ "g1", },
+               .num_clks = 1,
+               .gpc_name = "g1",
+               .rst_mask = BIT(1),
+               .clk_mask = BIT(1),
+       },
+       [IMX8MQ_VPUBLK_PD_G2] = {
+               .name = "vpublk-g2",
+               .clk_names = (const char *[]){ "g2", },
+               .num_clks = 1,
+               .gpc_name = "g2",
+               .rst_mask = BIT(0),
+               .clk_mask = BIT(0),
+       },
+};
+
+static const struct imx8m_blk_ctrl_data imx8mq_vpu_blk_ctl_dev_data = {
+       .max_reg = 0x14,
+       .power_notifier_fn = imx8mq_vpu_power_notifier,
+       .domains = imx8mq_vpu_blk_ctl_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mq_vpu_blk_ctl_domain_data),
+};
+
+static const struct of_device_id imx8m_blk_ctrl_of_match[] = {
+       {
+               .compatible = "fsl,imx8mm-vpu-blk-ctrl",
+               .data = &imx8mm_vpu_blk_ctl_dev_data
+       }, {
+               .compatible = "fsl,imx8mm-disp-blk-ctrl",
+               .data = &imx8mm_disp_blk_ctl_dev_data
+       }, {
+               .compatible = "fsl,imx8mn-disp-blk-ctrl",
+               .data = &imx8mn_disp_blk_ctl_dev_data
+       }, {
+               .compatible = "fsl,imx8mp-media-blk-ctrl",
+               .data = &imx8mp_media_blk_ctl_dev_data
+       }, {
+               .compatible = "fsl,imx8mq-vpu-blk-ctrl",
+               .data = &imx8mq_vpu_blk_ctl_dev_data
+       }, {
+               .compatible = "fsl,imx8mp-vpu-blk-ctrl",
+               .data = &imx8mp_vpu_blk_ctl_dev_data
+       }, {
+               /* Sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(of, imx8m_blk_ctrl_of_match);
+
+static struct platform_driver imx8m_blk_ctrl_driver = {
+       .probe = imx8m_blk_ctrl_probe,
+       .remove = imx8m_blk_ctrl_remove,
+       .driver = {
+               .name = "imx8m-blk-ctrl",
+               .pm = &imx8m_blk_ctrl_pm_ops,
+               .of_match_table = imx8m_blk_ctrl_of_match,
+       },
+};
+module_platform_driver(imx8m_blk_ctrl_driver);
+MODULE_LICENSE("GPL");
diff --git a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
new file mode 100644 (file)
index 0000000..c6ac32c
--- /dev/null
@@ -0,0 +1,867 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Copyright 2022 Pengutronix, Lucas Stach <kernel@pengutronix.de>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/interconnect.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/power/imx8mp-power.h>
+
+#define GPR_REG0               0x0
+#define  PCIE_CLOCK_MODULE_EN  BIT(0)
+#define  USB_CLOCK_MODULE_EN   BIT(1)
+#define  PCIE_PHY_APB_RST      BIT(4)
+#define  PCIE_PHY_INIT_RST     BIT(5)
+#define GPR_REG1               0x4
+#define  PLL_LOCK              BIT(13)
+#define GPR_REG2               0x8
+#define  P_PLL_MASK            GENMASK(5, 0)
+#define  M_PLL_MASK            GENMASK(15, 6)
+#define  S_PLL_MASK            GENMASK(18, 16)
+#define GPR_REG3               0xc
+#define  PLL_CKE               BIT(17)
+#define  PLL_RST               BIT(31)
+
+struct imx8mp_blk_ctrl_domain;
+
+struct imx8mp_blk_ctrl {
+       struct device *dev;
+       struct notifier_block power_nb;
+       struct device *bus_power_dev;
+       struct regmap *regmap;
+       struct imx8mp_blk_ctrl_domain *domains;
+       struct genpd_onecell_data onecell_data;
+       void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
+       void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
+};
+
+struct imx8mp_blk_ctrl_domain_data {
+       const char *name;
+       const char * const *clk_names;
+       int num_clks;
+       const char * const *path_names;
+       int num_paths;
+       const char *gpc_name;
+};
+
+#define DOMAIN_MAX_CLKS 2
+#define DOMAIN_MAX_PATHS 3
+
+struct imx8mp_blk_ctrl_domain {
+       struct generic_pm_domain genpd;
+       const struct imx8mp_blk_ctrl_domain_data *data;
+       struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
+       struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
+       struct device *power_dev;
+       struct imx8mp_blk_ctrl *bc;
+       int num_paths;
+       int id;
+};
+
+struct imx8mp_blk_ctrl_data {
+       int max_reg;
+       int (*probe) (struct imx8mp_blk_ctrl *bc);
+       notifier_fn_t power_notifier_fn;
+       void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
+       void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
+       const struct imx8mp_blk_ctrl_domain_data *domains;
+       int num_domains;
+};
+
+static inline struct imx8mp_blk_ctrl_domain *
+to_imx8mp_blk_ctrl_domain(struct generic_pm_domain *genpd)
+{
+       return container_of(genpd, struct imx8mp_blk_ctrl_domain, genpd);
+}
+
+struct clk_hsio_pll {
+       struct clk_hw   hw;
+       struct regmap *regmap;
+};
+
+static inline struct clk_hsio_pll *to_clk_hsio_pll(struct clk_hw *hw)
+{
+       return container_of(hw, struct clk_hsio_pll, hw);
+}
+
+static int clk_hsio_pll_prepare(struct clk_hw *hw)
+{
+       struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
+       u32 val;
+
+       /* set the PLL configuration */
+       regmap_update_bits(clk->regmap, GPR_REG2,
+                          P_PLL_MASK | M_PLL_MASK | S_PLL_MASK,
+                          FIELD_PREP(P_PLL_MASK, 12) |
+                          FIELD_PREP(M_PLL_MASK, 800) |
+                          FIELD_PREP(S_PLL_MASK, 4));
+
+       /* de-assert PLL reset */
+       regmap_update_bits(clk->regmap, GPR_REG3, PLL_RST, PLL_RST);
+
+       /* enable PLL */
+       regmap_update_bits(clk->regmap, GPR_REG3, PLL_CKE, PLL_CKE);
+
+       return regmap_read_poll_timeout(clk->regmap, GPR_REG1, val,
+                                       val & PLL_LOCK, 10, 100);
+}
+
+static void clk_hsio_pll_unprepare(struct clk_hw *hw)
+{
+       struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
+
+       regmap_update_bits(clk->regmap, GPR_REG3, PLL_RST | PLL_CKE, 0);
+}
+
+static int clk_hsio_pll_is_prepared(struct clk_hw *hw)
+{
+       struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
+
+       return regmap_test_bits(clk->regmap, GPR_REG1, PLL_LOCK);
+}
+
+static unsigned long clk_hsio_pll_recalc_rate(struct clk_hw *hw,
+                                             unsigned long parent_rate)
+{
+       return 100000000;
+}
+
+static const struct clk_ops clk_hsio_pll_ops = {
+       .prepare = clk_hsio_pll_prepare,
+       .unprepare = clk_hsio_pll_unprepare,
+       .is_prepared = clk_hsio_pll_is_prepared,
+       .recalc_rate = clk_hsio_pll_recalc_rate,
+};
+
+static int imx8mp_hsio_blk_ctrl_probe(struct imx8mp_blk_ctrl *bc)
+{
+       struct clk_hsio_pll *clk_hsio_pll;
+       struct clk_hw *hw;
+       struct clk_init_data init = {};
+       int ret;
+
+       clk_hsio_pll = devm_kzalloc(bc->dev, sizeof(*clk_hsio_pll), GFP_KERNEL);
+       if (!clk_hsio_pll)
+               return -ENOMEM;
+
+       init.name = "hsio_pll";
+       init.ops = &clk_hsio_pll_ops;
+       init.parent_names = (const char *[]){"osc_24m"};
+       init.num_parents = 1;
+
+       clk_hsio_pll->regmap = bc->regmap;
+       clk_hsio_pll->hw.init = &init;
+
+       hw = &clk_hsio_pll->hw;
+       ret = devm_clk_hw_register(bc->bus_power_dev, hw);
+       if (ret)
+               return ret;
+
+       return devm_of_clk_add_hw_provider(bc->dev, of_clk_hw_simple_get, hw);
+}
+
+static void imx8mp_hsio_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
+                                         struct imx8mp_blk_ctrl_domain *domain)
+{
+       switch (domain->id) {
+       case IMX8MP_HSIOBLK_PD_USB:
+               regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
+               break;
+       case IMX8MP_HSIOBLK_PD_PCIE:
+               regmap_set_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
+               break;
+       case IMX8MP_HSIOBLK_PD_PCIE_PHY:
+               regmap_set_bits(bc->regmap, GPR_REG0,
+                               PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST);
+               break;
+       default:
+               break;
+       }
+}
+
+static void imx8mp_hsio_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
+                                          struct imx8mp_blk_ctrl_domain *domain)
+{
+       switch (domain->id) {
+       case IMX8MP_HSIOBLK_PD_USB:
+               regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
+               break;
+       case IMX8MP_HSIOBLK_PD_PCIE:
+               regmap_clear_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
+               break;
+       case IMX8MP_HSIOBLK_PD_PCIE_PHY:
+               regmap_clear_bits(bc->regmap, GPR_REG0,
+                                 PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST);
+               break;
+       default:
+               break;
+       }
+}
+
+static int imx8mp_hsio_power_notifier(struct notifier_block *nb,
+                                     unsigned long action, void *data)
+{
+       struct imx8mp_blk_ctrl *bc = container_of(nb, struct imx8mp_blk_ctrl,
+                                                power_nb);
+       struct clk_bulk_data *usb_clk = bc->domains[IMX8MP_HSIOBLK_PD_USB].clks;
+       int num_clks = bc->domains[IMX8MP_HSIOBLK_PD_USB].data->num_clks;
+       int ret;
+
+       switch (action) {
+       case GENPD_NOTIFY_ON:
+               /*
+                * enable USB clock for a moment for the power-on ADB handshake
+                * to proceed
+                */
+               ret = clk_bulk_prepare_enable(num_clks, usb_clk);
+               if (ret)
+                       return NOTIFY_BAD;
+               regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
+
+               udelay(5);
+
+               regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
+               clk_bulk_disable_unprepare(num_clks, usb_clk);
+               break;
+       case GENPD_NOTIFY_PRE_OFF:
+               /* enable USB clock for the power-down ADB handshake to work */
+               ret = clk_bulk_prepare_enable(num_clks, usb_clk);
+               if (ret)
+                       return NOTIFY_BAD;
+
+               regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
+               break;
+       case GENPD_NOTIFY_OFF:
+               clk_bulk_disable_unprepare(num_clks, usb_clk);
+               break;
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = {
+       [IMX8MP_HSIOBLK_PD_USB] = {
+               .name = "hsioblk-usb",
+               .clk_names = (const char *[]){ "usb" },
+               .num_clks = 1,
+               .gpc_name = "usb",
+               .path_names = (const char *[]){"usb1", "usb2"},
+               .num_paths = 2,
+       },
+       [IMX8MP_HSIOBLK_PD_USB_PHY1] = {
+               .name = "hsioblk-usb-phy1",
+               .gpc_name = "usb-phy1",
+       },
+       [IMX8MP_HSIOBLK_PD_USB_PHY2] = {
+               .name = "hsioblk-usb-phy2",
+               .gpc_name = "usb-phy2",
+       },
+       [IMX8MP_HSIOBLK_PD_PCIE] = {
+               .name = "hsioblk-pcie",
+               .clk_names = (const char *[]){ "pcie" },
+               .num_clks = 1,
+               .gpc_name = "pcie",
+               .path_names = (const char *[]){"noc-pcie", "pcie"},
+               .num_paths = 2,
+       },
+       [IMX8MP_HSIOBLK_PD_PCIE_PHY] = {
+               .name = "hsioblk-pcie-phy",
+               .gpc_name = "pcie-phy",
+       },
+};
+
+static const struct imx8mp_blk_ctrl_data imx8mp_hsio_blk_ctl_dev_data = {
+       .max_reg = 0x24,
+       .probe = imx8mp_hsio_blk_ctrl_probe,
+       .power_on = imx8mp_hsio_blk_ctrl_power_on,
+       .power_off = imx8mp_hsio_blk_ctrl_power_off,
+       .power_notifier_fn = imx8mp_hsio_power_notifier,
+       .domains = imx8mp_hsio_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mp_hsio_domain_data),
+};
+
+#define HDMI_RTX_RESET_CTL0    0x20
+#define HDMI_RTX_CLK_CTL0      0x40
+#define HDMI_RTX_CLK_CTL1      0x50
+#define HDMI_RTX_CLK_CTL2      0x60
+#define HDMI_RTX_CLK_CTL3      0x70
+#define HDMI_RTX_CLK_CTL4      0x80
+#define HDMI_TX_CONTROL0       0x200
+#define  HDMI_LCDIF_NOC_HURRY_MASK             GENMASK(14, 12)
+
+static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
+                                         struct imx8mp_blk_ctrl_domain *domain)
+{
+       switch (domain->id) {
+       case IMX8MP_HDMIBLK_PD_IRQSTEER:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(9));
+               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(16));
+               break;
+       case IMX8MP_HDMIBLK_PD_LCDIF:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
+                               BIT(16) | BIT(17) | BIT(18) |
+                               BIT(19) | BIT(20));
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11));
+               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
+                               BIT(4) | BIT(5) | BIT(6));
+               regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0,
+                               FIELD_PREP(HDMI_LCDIF_NOC_HURRY_MASK, 7));
+               break;
+       case IMX8MP_HDMIBLK_PD_PAI:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17));
+               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(18));
+               break;
+       case IMX8MP_HDMIBLK_PD_PVI:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(28));
+               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(22));
+               break;
+       case IMX8MP_HDMIBLK_PD_TRNG:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(27) | BIT(30));
+               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(20));
+               break;
+       case IMX8MP_HDMIBLK_PD_HDMI_TX:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
+                               BIT(2) | BIT(4) | BIT(5));
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1,
+                               BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) |
+                               BIT(18) | BIT(19) | BIT(20) | BIT(21));
+               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
+                               BIT(7) | BIT(10) | BIT(11));
+               regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1));
+               break;
+       case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7));
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
+               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
+               regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
+               break;
+       case IMX8MP_HDMIBLK_PD_HDCP:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11));
+               break;
+       case IMX8MP_HDMIBLK_PD_HRV:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5));
+               regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15));
+               break;
+       default:
+               break;
+       }
+}
+
+static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
+                                          struct imx8mp_blk_ctrl_domain *domain)
+{
+       switch (domain->id) {
+       case IMX8MP_HDMIBLK_PD_IRQSTEER:
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(9));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(16));
+               break;
+       case IMX8MP_HDMIBLK_PD_LCDIF:
+               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
+                                 BIT(4) | BIT(5) | BIT(6));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
+                                 BIT(16) | BIT(17) | BIT(18) |
+                                 BIT(19) | BIT(20));
+               break;
+       case IMX8MP_HDMIBLK_PD_PAI:
+               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(18));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(17));
+               break;
+       case IMX8MP_HDMIBLK_PD_PVI:
+               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(22));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(28));
+               break;
+       case IMX8MP_HDMIBLK_PD_TRNG:
+               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(20));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(27) | BIT(30));
+               break;
+       case IMX8MP_HDMIBLK_PD_HDMI_TX:
+               regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
+                                 BIT(7) | BIT(10) | BIT(11));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1,
+                                 BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) |
+                                 BIT(18) | BIT(19) | BIT(20) | BIT(21));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
+                                 BIT(2) | BIT(4) | BIT(5));
+               break;
+       case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY:
+               regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
+               break;
+       case IMX8MP_HDMIBLK_PD_HDCP:
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11));
+               break;
+       case IMX8MP_HDMIBLK_PD_HRV:
+               regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5));
+               break;
+       default:
+               break;
+       }
+}
+
+static int imx8mp_hdmi_power_notifier(struct notifier_block *nb,
+                                     unsigned long action, void *data)
+{
+       struct imx8mp_blk_ctrl *bc = container_of(nb, struct imx8mp_blk_ctrl,
+                                                power_nb);
+
+       if (action != GENPD_NOTIFY_ON)
+               return NOTIFY_OK;
+
+       /*
+        * Contrary to other blk-ctrls the reset and clock don't clear when the
+        * power domain is powered down. To ensure the proper reset pulsing,
+        * first clear them all to asserted state, then enable the bus clocks
+        * and then release the ADB reset.
+        */
+       regmap_write(bc->regmap, HDMI_RTX_RESET_CTL0, 0x0);
+       regmap_write(bc->regmap, HDMI_RTX_CLK_CTL0, 0x0);
+       regmap_write(bc->regmap, HDMI_RTX_CLK_CTL1, 0x0);
+       regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
+                       BIT(0) | BIT(1) | BIT(10));
+       regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(0));
+
+       /*
+        * On power up we have no software backchannel to the GPC to
+        * wait for the ADB handshake to happen, so we just delay for a
+        * bit. On power down the GPC driver waits for the handshake.
+        */
+       udelay(5);
+
+       return NOTIFY_OK;
+}
+
+static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = {
+       [IMX8MP_HDMIBLK_PD_IRQSTEER] = {
+               .name = "hdmiblk-irqsteer",
+               .clk_names = (const char *[]){ "apb" },
+               .num_clks = 1,
+               .gpc_name = "irqsteer",
+       },
+       [IMX8MP_HDMIBLK_PD_LCDIF] = {
+               .name = "hdmiblk-lcdif",
+               .clk_names = (const char *[]){ "axi", "apb" },
+               .num_clks = 2,
+               .gpc_name = "lcdif",
+               .path_names = (const char *[]){"lcdif-hdmi"},
+               .num_paths = 1,
+       },
+       [IMX8MP_HDMIBLK_PD_PAI] = {
+               .name = "hdmiblk-pai",
+               .clk_names = (const char *[]){ "apb" },
+               .num_clks = 1,
+               .gpc_name = "pai",
+       },
+       [IMX8MP_HDMIBLK_PD_PVI] = {
+               .name = "hdmiblk-pvi",
+               .clk_names = (const char *[]){ "apb" },
+               .num_clks = 1,
+               .gpc_name = "pvi",
+       },
+       [IMX8MP_HDMIBLK_PD_TRNG] = {
+               .name = "hdmiblk-trng",
+               .clk_names = (const char *[]){ "apb" },
+               .num_clks = 1,
+               .gpc_name = "trng",
+       },
+       [IMX8MP_HDMIBLK_PD_HDMI_TX] = {
+               .name = "hdmiblk-hdmi-tx",
+               .clk_names = (const char *[]){ "apb", "ref_266m" },
+               .num_clks = 2,
+               .gpc_name = "hdmi-tx",
+       },
+       [IMX8MP_HDMIBLK_PD_HDMI_TX_PHY] = {
+               .name = "hdmiblk-hdmi-tx-phy",
+               .clk_names = (const char *[]){ "apb", "ref_24m" },
+               .num_clks = 2,
+               .gpc_name = "hdmi-tx-phy",
+       },
+       [IMX8MP_HDMIBLK_PD_HRV] = {
+               .name = "hdmiblk-hrv",
+               .clk_names = (const char *[]){ "axi", "apb" },
+               .num_clks = 2,
+               .gpc_name = "hrv",
+               .path_names = (const char *[]){"hrv"},
+               .num_paths = 1,
+       },
+       [IMX8MP_HDMIBLK_PD_HDCP] = {
+               .name = "hdmiblk-hdcp",
+               .clk_names = (const char *[]){ "axi", "apb" },
+               .num_clks = 2,
+               .gpc_name = "hdcp",
+               .path_names = (const char *[]){"hdcp"},
+               .num_paths = 1,
+       },
+};
+
+static const struct imx8mp_blk_ctrl_data imx8mp_hdmi_blk_ctl_dev_data = {
+       .max_reg = 0x23c,
+       .power_on = imx8mp_hdmi_blk_ctrl_power_on,
+       .power_off = imx8mp_hdmi_blk_ctrl_power_off,
+       .power_notifier_fn = imx8mp_hdmi_power_notifier,
+       .domains = imx8mp_hdmi_domain_data,
+       .num_domains = ARRAY_SIZE(imx8mp_hdmi_domain_data),
+};
+
+static int imx8mp_blk_ctrl_power_on(struct generic_pm_domain *genpd)
+{
+       struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd);
+       const struct imx8mp_blk_ctrl_domain_data *data = domain->data;
+       struct imx8mp_blk_ctrl *bc = domain->bc;
+       int ret;
+
+       /* make sure bus domain is awake */
+       ret = pm_runtime_resume_and_get(bc->bus_power_dev);
+       if (ret < 0) {
+               dev_err(bc->dev, "failed to power up bus domain\n");
+               return ret;
+       }
+
+       /* enable upstream clocks */
+       ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
+       if (ret) {
+               dev_err(bc->dev, "failed to enable clocks\n");
+               goto bus_put;
+       }
+
+       /* domain specific blk-ctrl manipulation */
+       bc->power_on(bc, domain);
+
+       /* power up upstream GPC domain */
+       ret = pm_runtime_resume_and_get(domain->power_dev);
+       if (ret < 0) {
+               dev_err(bc->dev, "failed to power up peripheral domain\n");
+               goto clk_disable;
+       }
+
+       ret = icc_bulk_set_bw(domain->num_paths, domain->paths);
+       if (ret)
+               dev_err(bc->dev, "failed to set icc bw\n");
+
+       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+
+       return 0;
+
+clk_disable:
+       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+bus_put:
+       pm_runtime_put(bc->bus_power_dev);
+
+       return ret;
+}
+
+static int imx8mp_blk_ctrl_power_off(struct generic_pm_domain *genpd)
+{
+       struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd);
+       const struct imx8mp_blk_ctrl_domain_data *data = domain->data;
+       struct imx8mp_blk_ctrl *bc = domain->bc;
+       int ret;
+
+       ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
+       if (ret) {
+               dev_err(bc->dev, "failed to enable clocks\n");
+               return ret;
+       }
+
+       /* domain specific blk-ctrl manipulation */
+       bc->power_off(bc, domain);
+
+       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+
+       /* power down upstream GPC domain */
+       pm_runtime_put(domain->power_dev);
+
+       /* allow bus domain to suspend */
+       pm_runtime_put(bc->bus_power_dev);
+
+       return 0;
+}
+
+static struct lock_class_key blk_ctrl_genpd_lock_class;
+
+static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
+{
+       const struct imx8mp_blk_ctrl_data *bc_data;
+       struct device *dev = &pdev->dev;
+       struct imx8mp_blk_ctrl *bc;
+       void __iomem *base;
+       int num_domains, i, ret;
+
+       struct regmap_config regmap_config = {
+               .reg_bits       = 32,
+               .val_bits       = 32,
+               .reg_stride     = 4,
+       };
+
+       bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
+       if (!bc)
+               return -ENOMEM;
+
+       bc->dev = dev;
+
+       bc_data = of_device_get_match_data(dev);
+       num_domains = bc_data->num_domains;
+
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       regmap_config.max_register = bc_data->max_reg;
+       bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
+       if (IS_ERR(bc->regmap))
+               return dev_err_probe(dev, PTR_ERR(bc->regmap),
+                                    "failed to init regmap\n");
+
+       bc->domains = devm_kcalloc(dev, num_domains,
+                                  sizeof(struct imx8mp_blk_ctrl_domain),
+                                  GFP_KERNEL);
+       if (!bc->domains)
+               return -ENOMEM;
+
+       bc->onecell_data.num_domains = num_domains;
+       bc->onecell_data.domains =
+               devm_kcalloc(dev, num_domains,
+                            sizeof(struct generic_pm_domain *), GFP_KERNEL);
+       if (!bc->onecell_data.domains)
+               return -ENOMEM;
+
+       bc->bus_power_dev = dev_pm_domain_attach_by_name(dev, "bus");
+       if (IS_ERR(bc->bus_power_dev))
+               return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
+                                    "failed to attach bus power domain\n");
+
+       bc->power_off = bc_data->power_off;
+       bc->power_on = bc_data->power_on;
+
+       for (i = 0; i < num_domains; i++) {
+               const struct imx8mp_blk_ctrl_domain_data *data = &bc_data->domains[i];
+               struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
+               int j;
+
+               domain->data = data;
+               domain->num_paths = data->num_paths;
+
+               for (j = 0; j < data->num_clks; j++)
+                       domain->clks[j].id = data->clk_names[j];
+
+               for (j = 0; j < data->num_paths; j++) {
+                       domain->paths[j].name = data->path_names[j];
+                       /* Fake value for now, just let ICC could configure NoC mode/priority */
+                       domain->paths[j].avg_bw = 1;
+                       domain->paths[j].peak_bw = 1;
+               }
+
+               ret = devm_of_icc_bulk_get(dev, data->num_paths, domain->paths);
+               if (ret) {
+                       if (ret != -EPROBE_DEFER) {
+                               dev_warn_once(dev, "Could not get interconnect paths, NoC will stay unconfigured!\n");
+                               domain->num_paths = 0;
+                       } else {
+                               dev_err_probe(dev, ret, "failed to get noc entries\n");
+                               goto cleanup_pds;
+                       }
+               }
+
+               ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
+               if (ret) {
+                       dev_err_probe(dev, ret, "failed to get clock\n");
+                       goto cleanup_pds;
+               }
+
+               domain->power_dev =
+                       dev_pm_domain_attach_by_name(dev, data->gpc_name);
+               if (IS_ERR(domain->power_dev)) {
+                       dev_err_probe(dev, PTR_ERR(domain->power_dev),
+                                     "failed to attach power domain %s\n",
+                                     data->gpc_name);
+                       ret = PTR_ERR(domain->power_dev);
+                       goto cleanup_pds;
+               }
+
+               domain->genpd.name = data->name;
+               domain->genpd.power_on = imx8mp_blk_ctrl_power_on;
+               domain->genpd.power_off = imx8mp_blk_ctrl_power_off;
+               domain->bc = bc;
+               domain->id = i;
+
+               ret = pm_genpd_init(&domain->genpd, NULL, true);
+               if (ret) {
+                       dev_err_probe(dev, ret, "failed to init power domain\n");
+                       dev_pm_domain_detach(domain->power_dev, true);
+                       goto cleanup_pds;
+               }
+
+               /*
+                * We use runtime PM to trigger power on/off of the upstream GPC
+                * domain, as a strict hierarchical parent/child power domain
+                * setup doesn't allow us to meet the sequencing requirements.
+                * This means we have nested locking of genpd locks, without the
+                * nesting being visible at the genpd level, so we need a
+                * separate lock class to make lockdep aware of the fact that
+                * this are separate domain locks that can be nested without a
+                * self-deadlock.
+                */
+               lockdep_set_class(&domain->genpd.mlock,
+                                 &blk_ctrl_genpd_lock_class);
+
+               bc->onecell_data.domains[i] = &domain->genpd;
+       }
+
+       ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
+       if (ret) {
+               dev_err_probe(dev, ret, "failed to add power domain provider\n");
+               goto cleanup_pds;
+       }
+
+       bc->power_nb.notifier_call = bc_data->power_notifier_fn;
+       ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb);
+       if (ret) {
+               dev_err_probe(dev, ret, "failed to add power notifier\n");
+               goto cleanup_provider;
+       }
+
+       if (bc_data->probe) {
+               ret = bc_data->probe(bc);
+               if (ret)
+                       goto cleanup_provider;
+       }
+
+       dev_set_drvdata(dev, bc);
+
+       return 0;
+
+cleanup_provider:
+       of_genpd_del_provider(dev->of_node);
+cleanup_pds:
+       for (i--; i >= 0; i--) {
+               pm_genpd_remove(&bc->domains[i].genpd);
+               dev_pm_domain_detach(bc->domains[i].power_dev, true);
+       }
+
+       dev_pm_domain_detach(bc->bus_power_dev, true);
+
+       return ret;
+}
+
+static int imx8mp_blk_ctrl_remove(struct platform_device *pdev)
+{
+       struct imx8mp_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
+       int i;
+
+       of_genpd_del_provider(pdev->dev.of_node);
+
+       for (i = 0; bc->onecell_data.num_domains; i++) {
+               struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
+
+               pm_genpd_remove(&domain->genpd);
+               dev_pm_domain_detach(domain->power_dev, true);
+       }
+
+       dev_pm_genpd_remove_notifier(bc->bus_power_dev);
+
+       dev_pm_domain_detach(bc->bus_power_dev, true);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int imx8mp_blk_ctrl_suspend(struct device *dev)
+{
+       struct imx8mp_blk_ctrl *bc = dev_get_drvdata(dev);
+       int ret, i;
+
+       /*
+        * This may look strange, but is done so the generic PM_SLEEP code
+        * can power down our domains and more importantly power them up again
+        * after resume, without tripping over our usage of runtime PM to
+        * control the upstream GPC domains. Things happen in the right order
+        * in the system suspend/resume paths due to the device parent/child
+        * hierarchy.
+        */
+       ret = pm_runtime_get_sync(bc->bus_power_dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(bc->bus_power_dev);
+               return ret;
+       }
+
+       for (i = 0; i < bc->onecell_data.num_domains; i++) {
+               struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
+
+               ret = pm_runtime_get_sync(domain->power_dev);
+               if (ret < 0) {
+                       pm_runtime_put_noidle(domain->power_dev);
+                       goto out_fail;
+               }
+       }
+
+       return 0;
+
+out_fail:
+       for (i--; i >= 0; i--)
+               pm_runtime_put(bc->domains[i].power_dev);
+
+       pm_runtime_put(bc->bus_power_dev);
+
+       return ret;
+}
+
+static int imx8mp_blk_ctrl_resume(struct device *dev)
+{
+       struct imx8mp_blk_ctrl *bc = dev_get_drvdata(dev);
+       int i;
+
+       for (i = 0; i < bc->onecell_data.num_domains; i++)
+               pm_runtime_put(bc->domains[i].power_dev);
+
+       pm_runtime_put(bc->bus_power_dev);
+
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops imx8mp_blk_ctrl_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(imx8mp_blk_ctrl_suspend,
+                               imx8mp_blk_ctrl_resume)
+};
+
+static const struct of_device_id imx8mp_blk_ctrl_of_match[] = {
+       {
+               .compatible = "fsl,imx8mp-hsio-blk-ctrl",
+               .data = &imx8mp_hsio_blk_ctl_dev_data,
+       }, {
+               .compatible = "fsl,imx8mp-hdmi-blk-ctrl",
+               .data = &imx8mp_hdmi_blk_ctl_dev_data,
+       }, {
+               /* Sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(of, imx8mp_blk_ctrl_of_match);
+
+static struct platform_driver imx8mp_blk_ctrl_driver = {
+       .probe = imx8mp_blk_ctrl_probe,
+       .remove = imx8mp_blk_ctrl_remove,
+       .driver = {
+               .name = "imx8mp-blk-ctrl",
+               .pm = &imx8mp_blk_ctrl_pm_ops,
+               .of_match_table = imx8mp_blk_ctrl_of_match,
+       },
+};
+module_platform_driver(imx8mp_blk_ctrl_driver);
+MODULE_LICENSE("GPL");
diff --git a/drivers/pmdomain/imx/imx93-blk-ctrl.c b/drivers/pmdomain/imx/imx93-blk-ctrl.c
new file mode 100644 (file)
index 0000000..40bd90f
--- /dev/null
@@ -0,0 +1,451 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2022 NXP, Peng Fan <peng.fan@nxp.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/sizes.h>
+
+#include <dt-bindings/power/fsl,imx93-power.h>
+
+#define BLK_SFT_RSTN   0x0
+#define BLK_CLK_EN     0x4
+#define BLK_MAX_CLKS   4
+
+#define DOMAIN_MAX_CLKS 4
+
+#define LCDIF_QOS_REG          0xC
+#define LCDIF_DEFAULT_QOS_OFF  12
+#define LCDIF_CFG_QOS_OFF      8
+
+#define PXP_QOS_REG            0x10
+#define PXP_R_DEFAULT_QOS_OFF  28
+#define PXP_R_CFG_QOS_OFF      24
+#define PXP_W_DEFAULT_QOS_OFF  20
+#define PXP_W_CFG_QOS_OFF      16
+
+#define ISI_CACHE_REG          0x14
+
+#define ISI_QOS_REG            0x1C
+#define ISI_V_DEFAULT_QOS_OFF  28
+#define ISI_V_CFG_QOS_OFF      24
+#define ISI_U_DEFAULT_QOS_OFF  20
+#define ISI_U_CFG_QOS_OFF      16
+#define ISI_Y_R_DEFAULT_QOS_OFF        12
+#define ISI_Y_R_CFG_QOS_OFF    8
+#define ISI_Y_W_DEFAULT_QOS_OFF        4
+#define ISI_Y_W_CFG_QOS_OFF    0
+
+#define PRIO_MASK              0xF
+
+#define PRIO(X)                        (X)
+
+struct imx93_blk_ctrl_domain;
+
+struct imx93_blk_ctrl {
+       struct device *dev;
+       struct regmap *regmap;
+       int num_clks;
+       struct clk_bulk_data clks[BLK_MAX_CLKS];
+       struct imx93_blk_ctrl_domain *domains;
+       struct genpd_onecell_data onecell_data;
+};
+
+#define DOMAIN_MAX_QOS 4
+
+struct imx93_blk_ctrl_qos {
+       u32 reg;
+       u32 cfg_off;
+       u32 default_prio;
+       u32 cfg_prio;
+};
+
+struct imx93_blk_ctrl_domain_data {
+       const char *name;
+       const char * const *clk_names;
+       int num_clks;
+       u32 rst_mask;
+       u32 clk_mask;
+       int num_qos;
+       struct imx93_blk_ctrl_qos qos[DOMAIN_MAX_QOS];
+};
+
+struct imx93_blk_ctrl_domain {
+       struct generic_pm_domain genpd;
+       const struct imx93_blk_ctrl_domain_data *data;
+       struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
+       struct imx93_blk_ctrl *bc;
+};
+
+struct imx93_blk_ctrl_data {
+       const struct imx93_blk_ctrl_domain_data *domains;
+       int num_domains;
+       const char * const *clk_names;
+       int num_clks;
+       const struct regmap_access_table *reg_access_table;
+};
+
+static inline struct imx93_blk_ctrl_domain *
+to_imx93_blk_ctrl_domain(struct generic_pm_domain *genpd)
+{
+       return container_of(genpd, struct imx93_blk_ctrl_domain, genpd);
+}
+
+static int imx93_blk_ctrl_set_qos(struct imx93_blk_ctrl_domain *domain)
+{
+       const struct imx93_blk_ctrl_domain_data *data = domain->data;
+       struct imx93_blk_ctrl *bc = domain->bc;
+       const struct imx93_blk_ctrl_qos *qos;
+       u32 val, mask;
+       int i;
+
+       for (i = 0; i < data->num_qos; i++) {
+               qos = &data->qos[i];
+
+               mask = PRIO_MASK << qos->cfg_off;
+               mask |= PRIO_MASK << (qos->cfg_off + 4);
+               val = qos->cfg_prio << qos->cfg_off;
+               val |= qos->default_prio << (qos->cfg_off + 4);
+
+               regmap_write_bits(bc->regmap, qos->reg, mask, val);
+
+               dev_dbg(bc->dev, "data->qos[i].reg 0x%x 0x%x\n", qos->reg, val);
+       }
+
+       return 0;
+}
+
+static int imx93_blk_ctrl_power_on(struct generic_pm_domain *genpd)
+{
+       struct imx93_blk_ctrl_domain *domain = to_imx93_blk_ctrl_domain(genpd);
+       const struct imx93_blk_ctrl_domain_data *data = domain->data;
+       struct imx93_blk_ctrl *bc = domain->bc;
+       int ret;
+
+       ret = clk_bulk_prepare_enable(bc->num_clks, bc->clks);
+       if (ret) {
+               dev_err(bc->dev, "failed to enable bus clocks\n");
+               return ret;
+       }
+
+       ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
+       if (ret) {
+               clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
+               dev_err(bc->dev, "failed to enable clocks\n");
+               return ret;
+       }
+
+       ret = pm_runtime_get_sync(bc->dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(bc->dev);
+               dev_err(bc->dev, "failed to power up domain\n");
+               goto disable_clk;
+       }
+
+       /* ungate clk */
+       regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
+
+       /* release reset */
+       regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
+
+       dev_dbg(bc->dev, "pd_on: name: %s\n", genpd->name);
+
+       return imx93_blk_ctrl_set_qos(domain);
+
+disable_clk:
+       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+
+       clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
+
+       return ret;
+}
+
+static int imx93_blk_ctrl_power_off(struct generic_pm_domain *genpd)
+{
+       struct imx93_blk_ctrl_domain *domain = to_imx93_blk_ctrl_domain(genpd);
+       const struct imx93_blk_ctrl_domain_data *data = domain->data;
+       struct imx93_blk_ctrl *bc = domain->bc;
+
+       dev_dbg(bc->dev, "pd_off: name: %s\n", genpd->name);
+
+       regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
+       regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
+
+       pm_runtime_put(bc->dev);
+
+       clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+
+       clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
+
+       return 0;
+}
+
+static struct lock_class_key blk_ctrl_genpd_lock_class;
+
+static int imx93_blk_ctrl_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       const struct imx93_blk_ctrl_data *bc_data = of_device_get_match_data(dev);
+       struct imx93_blk_ctrl *bc;
+       void __iomem *base;
+       int i, ret;
+
+       struct regmap_config regmap_config = {
+               .reg_bits       = 32,
+               .val_bits       = 32,
+               .reg_stride     = 4,
+               .rd_table       = bc_data->reg_access_table,
+               .wr_table       = bc_data->reg_access_table,
+               .max_register   = SZ_4K,
+       };
+
+       bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
+       if (!bc)
+               return -ENOMEM;
+
+       bc->dev = dev;
+
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
+       if (IS_ERR(bc->regmap))
+               return dev_err_probe(dev, PTR_ERR(bc->regmap),
+                                    "failed to init regmap\n");
+
+       bc->domains = devm_kcalloc(dev, bc_data->num_domains,
+                                  sizeof(struct imx93_blk_ctrl_domain),
+                                  GFP_KERNEL);
+       if (!bc->domains)
+               return -ENOMEM;
+
+       bc->onecell_data.num_domains = bc_data->num_domains;
+       bc->onecell_data.domains =
+               devm_kcalloc(dev, bc_data->num_domains,
+                            sizeof(struct generic_pm_domain *), GFP_KERNEL);
+       if (!bc->onecell_data.domains)
+               return -ENOMEM;
+
+       for (i = 0; i < bc_data->num_clks; i++)
+               bc->clks[i].id = bc_data->clk_names[i];
+       bc->num_clks = bc_data->num_clks;
+
+       ret = devm_clk_bulk_get(dev, bc->num_clks, bc->clks);
+       if (ret) {
+               dev_err_probe(dev, ret, "failed to get bus clock\n");
+               return ret;
+       }
+
+       for (i = 0; i < bc_data->num_domains; i++) {
+               const struct imx93_blk_ctrl_domain_data *data = &bc_data->domains[i];
+               struct imx93_blk_ctrl_domain *domain = &bc->domains[i];
+               int j;
+
+               domain->data = data;
+
+               for (j = 0; j < data->num_clks; j++)
+                       domain->clks[j].id = data->clk_names[j];
+
+               ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
+               if (ret) {
+                       dev_err_probe(dev, ret, "failed to get clock\n");
+                       goto cleanup_pds;
+               }
+
+               domain->genpd.name = data->name;
+               domain->genpd.power_on = imx93_blk_ctrl_power_on;
+               domain->genpd.power_off = imx93_blk_ctrl_power_off;
+               domain->bc = bc;
+
+               ret = pm_genpd_init(&domain->genpd, NULL, true);
+               if (ret) {
+                       dev_err_probe(dev, ret, "failed to init power domain\n");
+                       goto cleanup_pds;
+               }
+
+               /*
+                * We use runtime PM to trigger power on/off of the upstream GPC
+                * domain, as a strict hierarchical parent/child power domain
+                * setup doesn't allow us to meet the sequencing requirements.
+                * This means we have nested locking of genpd locks, without the
+                * nesting being visible at the genpd level, so we need a
+                * separate lock class to make lockdep aware of the fact that
+                * this are separate domain locks that can be nested without a
+                * self-deadlock.
+                */
+               lockdep_set_class(&domain->genpd.mlock,
+                                 &blk_ctrl_genpd_lock_class);
+
+               bc->onecell_data.domains[i] = &domain->genpd;
+       }
+
+       pm_runtime_enable(dev);
+
+       ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
+       if (ret) {
+               dev_err_probe(dev, ret, "failed to add power domain provider\n");
+               goto cleanup_pds;
+       }
+
+       dev_set_drvdata(dev, bc);
+
+       return 0;
+
+cleanup_pds:
+       for (i--; i >= 0; i--)
+               pm_genpd_remove(&bc->domains[i].genpd);
+
+       return ret;
+}
+
+static int imx93_blk_ctrl_remove(struct platform_device *pdev)
+{
+       struct imx93_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
+       int i;
+
+       of_genpd_del_provider(pdev->dev.of_node);
+
+       for (i = 0; bc->onecell_data.num_domains; i++) {
+               struct imx93_blk_ctrl_domain *domain = &bc->domains[i];
+
+               pm_genpd_remove(&domain->genpd);
+       }
+
+       return 0;
+}
+
+static const struct imx93_blk_ctrl_domain_data imx93_media_blk_ctl_domain_data[] = {
+       [IMX93_MEDIABLK_PD_MIPI_DSI] = {
+               .name = "mediablk-mipi-dsi",
+               .clk_names = (const char *[]){ "dsi" },
+               .num_clks = 1,
+               .rst_mask = BIT(11) | BIT(12),
+               .clk_mask = BIT(11) | BIT(12),
+       },
+       [IMX93_MEDIABLK_PD_MIPI_CSI] = {
+               .name = "mediablk-mipi-csi",
+               .clk_names = (const char *[]){ "cam", "csi" },
+               .num_clks = 2,
+               .rst_mask = BIT(9) | BIT(10),
+               .clk_mask = BIT(9) | BIT(10),
+       },
+       [IMX93_MEDIABLK_PD_PXP] = {
+               .name = "mediablk-pxp",
+               .clk_names = (const char *[]){ "pxp" },
+               .num_clks = 1,
+               .rst_mask = BIT(7) | BIT(8),
+               .clk_mask = BIT(7) | BIT(8),
+               .num_qos = 2,
+               .qos = {
+                       {
+                               .reg = PXP_QOS_REG,
+                               .cfg_off = PXP_R_CFG_QOS_OFF,
+                               .default_prio = PRIO(3),
+                               .cfg_prio = PRIO(6),
+                       }, {
+                               .reg = PXP_QOS_REG,
+                               .cfg_off = PXP_W_CFG_QOS_OFF,
+                               .default_prio = PRIO(3),
+                               .cfg_prio = PRIO(6),
+                       }
+               }
+       },
+       [IMX93_MEDIABLK_PD_LCDIF] = {
+               .name = "mediablk-lcdif",
+               .clk_names = (const char *[]){ "disp", "lcdif" },
+               .num_clks = 2,
+               .rst_mask = BIT(4) | BIT(5) | BIT(6),
+               .clk_mask = BIT(4) | BIT(5) | BIT(6),
+               .num_qos = 1,
+               .qos = {
+                       {
+                       .reg = LCDIF_QOS_REG,
+                       .cfg_off = LCDIF_CFG_QOS_OFF,
+                       .default_prio = PRIO(3),
+                       .cfg_prio = PRIO(7),
+                       }
+               }
+       },
+       [IMX93_MEDIABLK_PD_ISI] = {
+               .name = "mediablk-isi",
+               .clk_names = (const char *[]){ "isi" },
+               .num_clks = 1,
+               .rst_mask = BIT(2) | BIT(3),
+               .clk_mask = BIT(2) | BIT(3),
+               .num_qos = 4,
+               .qos = {
+                       {
+                               .reg = ISI_QOS_REG,
+                               .cfg_off = ISI_Y_W_CFG_QOS_OFF,
+                               .default_prio = PRIO(3),
+                               .cfg_prio = PRIO(7),
+                       }, {
+                               .reg = ISI_QOS_REG,
+                               .cfg_off = ISI_Y_R_CFG_QOS_OFF,
+                               .default_prio = PRIO(3),
+                               .cfg_prio = PRIO(7),
+                       }, {
+                               .reg = ISI_QOS_REG,
+                               .cfg_off = ISI_U_CFG_QOS_OFF,
+                               .default_prio = PRIO(3),
+                               .cfg_prio = PRIO(7),
+                       }, {
+                               .reg = ISI_QOS_REG,
+                               .cfg_off = ISI_V_CFG_QOS_OFF,
+                               .default_prio = PRIO(3),
+                               .cfg_prio = PRIO(7),
+                       }
+               }
+       },
+};
+
+static const struct regmap_range imx93_media_blk_ctl_yes_ranges[] = {
+       regmap_reg_range(BLK_SFT_RSTN, BLK_CLK_EN),
+       regmap_reg_range(LCDIF_QOS_REG, ISI_CACHE_REG),
+       regmap_reg_range(ISI_QOS_REG, ISI_QOS_REG),
+};
+
+static const struct regmap_access_table imx93_media_blk_ctl_access_table = {
+       .yes_ranges = imx93_media_blk_ctl_yes_ranges,
+       .n_yes_ranges = ARRAY_SIZE(imx93_media_blk_ctl_yes_ranges),
+};
+
+static const struct imx93_blk_ctrl_data imx93_media_blk_ctl_dev_data = {
+       .domains = imx93_media_blk_ctl_domain_data,
+       .num_domains = ARRAY_SIZE(imx93_media_blk_ctl_domain_data),
+       .clk_names = (const char *[]){ "axi", "apb", "nic", },
+       .num_clks = 3,
+       .reg_access_table = &imx93_media_blk_ctl_access_table,
+};
+
+static const struct of_device_id imx93_blk_ctrl_of_match[] = {
+       {
+               .compatible = "fsl,imx93-media-blk-ctrl",
+               .data = &imx93_media_blk_ctl_dev_data
+       }, {
+               /* Sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(of, imx93_blk_ctrl_of_match);
+
+static struct platform_driver imx93_blk_ctrl_driver = {
+       .probe = imx93_blk_ctrl_probe,
+       .remove = imx93_blk_ctrl_remove,
+       .driver = {
+               .name = "imx93-blk-ctrl",
+               .of_match_table = imx93_blk_ctrl_of_match,
+       },
+};
+module_platform_driver(imx93_blk_ctrl_driver);
+
+MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
+MODULE_DESCRIPTION("i.MX93 BLK CTRL driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pmdomain/imx/imx93-pd.c b/drivers/pmdomain/imx/imx93-pd.c
new file mode 100644 (file)
index 0000000..b9e60d1
--- /dev/null
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2022 NXP
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+
+#define MIX_SLICE_SW_CTRL_OFF          0x20
+#define SLICE_SW_CTRL_PSW_CTRL_OFF_MASK        BIT(4)
+#define SLICE_SW_CTRL_PDN_SOFT_MASK    BIT(31)
+
+#define MIX_FUNC_STAT_OFF              0xB4
+
+#define FUNC_STAT_PSW_STAT_MASK                BIT(0)
+#define FUNC_STAT_RST_STAT_MASK                BIT(2)
+#define FUNC_STAT_ISO_STAT_MASK                BIT(4)
+
+struct imx93_power_domain {
+       struct generic_pm_domain genpd;
+       struct device *dev;
+       void __iomem *addr;
+       struct clk_bulk_data *clks;
+       int num_clks;
+       bool init_off;
+};
+
+#define to_imx93_pd(_genpd) container_of(_genpd, struct imx93_power_domain, genpd)
+
+static int imx93_pd_on(struct generic_pm_domain *genpd)
+{
+       struct imx93_power_domain *domain = to_imx93_pd(genpd);
+       void __iomem *addr = domain->addr;
+       u32 val;
+       int ret;
+
+       ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
+       if (ret) {
+               dev_err(domain->dev, "failed to enable clocks for domain: %s\n", genpd->name);
+               return ret;
+       }
+
+       val = readl(addr + MIX_SLICE_SW_CTRL_OFF);
+       val &= ~SLICE_SW_CTRL_PDN_SOFT_MASK;
+       writel(val, addr + MIX_SLICE_SW_CTRL_OFF);
+
+       ret = readl_poll_timeout(addr + MIX_FUNC_STAT_OFF, val,
+                                !(val & FUNC_STAT_ISO_STAT_MASK), 1, 10000);
+       if (ret) {
+               dev_err(domain->dev, "pd_on timeout: name: %s, stat: %x\n", genpd->name, val);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int imx93_pd_off(struct generic_pm_domain *genpd)
+{
+       struct imx93_power_domain *domain = to_imx93_pd(genpd);
+       void __iomem *addr = domain->addr;
+       int ret;
+       u32 val;
+
+       /* Power off MIX */
+       val = readl(addr + MIX_SLICE_SW_CTRL_OFF);
+       val |= SLICE_SW_CTRL_PDN_SOFT_MASK;
+       writel(val, addr + MIX_SLICE_SW_CTRL_OFF);
+
+       ret = readl_poll_timeout(addr + MIX_FUNC_STAT_OFF, val,
+                                val & FUNC_STAT_PSW_STAT_MASK, 1, 1000);
+       if (ret) {
+               dev_err(domain->dev, "pd_off timeout: name: %s, stat: %x\n", genpd->name, val);
+               return ret;
+       }
+
+       clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+
+       return 0;
+};
+
+static int imx93_pd_remove(struct platform_device *pdev)
+{
+       struct imx93_power_domain *domain = platform_get_drvdata(pdev);
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+
+       if (!domain->init_off)
+               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+
+       of_genpd_del_provider(np);
+       pm_genpd_remove(&domain->genpd);
+
+       return 0;
+}
+
+static int imx93_pd_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct imx93_power_domain *domain;
+       int ret;
+
+       domain = devm_kzalloc(dev, sizeof(*domain), GFP_KERNEL);
+       if (!domain)
+               return -ENOMEM;
+
+       domain->addr = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(domain->addr))
+               return PTR_ERR(domain->addr);
+
+       domain->num_clks = devm_clk_bulk_get_all(dev, &domain->clks);
+       if (domain->num_clks < 0)
+               return dev_err_probe(dev, domain->num_clks, "Failed to get domain's clocks\n");
+
+       domain->genpd.name = dev_name(dev);
+       domain->genpd.power_off = imx93_pd_off;
+       domain->genpd.power_on = imx93_pd_on;
+       domain->dev = dev;
+
+       domain->init_off = readl(domain->addr + MIX_FUNC_STAT_OFF) & FUNC_STAT_ISO_STAT_MASK;
+       /* Just to sync the status of hardware */
+       if (!domain->init_off) {
+               ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
+               if (ret) {
+                       dev_err(domain->dev, "failed to enable clocks for domain: %s\n",
+                               domain->genpd.name);
+                       return ret;
+               }
+       }
+
+       ret = pm_genpd_init(&domain->genpd, NULL, domain->init_off);
+       if (ret)
+               goto err_clk_unprepare;
+
+       platform_set_drvdata(pdev, domain);
+
+       ret = of_genpd_add_provider_simple(np, &domain->genpd);
+       if (ret)
+               goto err_genpd_remove;
+
+       return 0;
+
+err_genpd_remove:
+       pm_genpd_remove(&domain->genpd);
+
+err_clk_unprepare:
+       if (!domain->init_off)
+               clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+
+       return ret;
+}
+
+static const struct of_device_id imx93_pd_ids[] = {
+       { .compatible = "fsl,imx93-src-slice" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, imx93_pd_ids);
+
+static struct platform_driver imx93_power_domain_driver = {
+       .driver = {
+               .name   = "imx93_power_domain",
+               .of_match_table = imx93_pd_ids,
+       },
+       .probe = imx93_pd_probe,
+       .remove = imx93_pd_remove,
+};
+module_platform_driver(imx93_power_domain_driver);
+
+MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
+MODULE_DESCRIPTION("NXP i.MX93 power domain driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pmdomain/imx/scu-pd.c b/drivers/pmdomain/imx/scu-pd.c
new file mode 100644 (file)
index 0000000..2f693b6
--- /dev/null
@@ -0,0 +1,550 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2018 NXP
+ *     Dong Aisheng <aisheng.dong@nxp.com>
+ *
+ * Implementation of the SCU based Power Domains
+ *
+ * NOTE: a better implementation suggested by Ulf Hansson is using a
+ * single global power domain and implement the ->attach|detach_dev()
+ * callback for the genpd and use the regular of_genpd_add_provider_simple().
+ * From within the ->attach_dev(), we could get the OF node for
+ * the device that is being attached and then parse the power-domain
+ * cell containing the "resource id" and store that in the per device
+ * struct generic_pm_domain_data (we have void pointer there for
+ * storing these kind of things).
+ *
+ * Additionally, we need to implement the ->stop() and ->start()
+ * callbacks of genpd, which is where you "power on/off" devices,
+ * rather than using the above ->power_on|off() callbacks.
+ *
+ * However, there're two known issues:
+ * 1. The ->attach_dev() of power domain infrastructure still does
+ *    not support multi domains case as the struct device *dev passed
+ *    in is a virtual PD device, it does not help for parsing the real
+ *    device resource id from device tree, so it's unware of which
+ *    real sub power domain of device should be attached.
+ *
+ *    The framework needs some proper extension to support multi power
+ *    domain cases.
+ *
+ *    Update: Genpd assigns the ->of_node for the virtual device before it
+ *    invokes ->attach_dev() callback, hence parsing for device resources via
+ *    DT should work fine.
+ *
+ * 2. It also breaks most of current drivers as the driver probe sequence
+ *    behavior changed if removing ->power_on|off() callback and use
+ *    ->start() and ->stop() instead. genpd_dev_pm_attach will only power
+ *    up the domain and attach device, but will not call .start() which
+ *    relies on device runtime pm. That means the device power is still
+ *    not up before running driver probe function. For SCU enabled
+ *    platforms, all device drivers accessing registers/clock without power
+ *    domain enabled will trigger a HW access error. That means we need fix
+ *    most drivers probe sequence with proper runtime pm.
+ *
+ *    Update: Runtime PM support isn't necessary. Instead, this can easily be
+ *    fixed in drivers by adding a call to dev_pm_domain_start() during probe.
+ *
+ * In summary, the second part needs to be addressed via minor updates to the
+ * relevant drivers, before the "single global power domain" model can be used.
+ *
+ */
+
+#include <dt-bindings/firmware/imx/rsrc.h>
+#include <linux/console.h>
+#include <linux/firmware/imx/sci.h>
+#include <linux/firmware/imx/svc/rm.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+
+/* SCU Power Mode Protocol definition */
+struct imx_sc_msg_req_set_resource_power_mode {
+       struct imx_sc_rpc_msg hdr;
+       u16 resource;
+       u8 mode;
+} __packed __aligned(4);
+
+struct req_get_resource_mode {
+       u16 resource;
+};
+
+struct resp_get_resource_mode {
+       u8 mode;
+};
+
+struct imx_sc_msg_req_get_resource_power_mode {
+       struct imx_sc_rpc_msg hdr;
+       union {
+               struct req_get_resource_mode req;
+               struct resp_get_resource_mode resp;
+       } data;
+} __packed __aligned(4);
+
+#define IMX_SCU_PD_NAME_SIZE 20
+struct imx_sc_pm_domain {
+       struct generic_pm_domain pd;
+       char name[IMX_SCU_PD_NAME_SIZE];
+       u32 rsrc;
+};
+
+struct imx_sc_pd_range {
+       char *name;
+       u32 rsrc;
+       u8 num;
+
+       /* add domain index */
+       bool postfix;
+       u8 start_from;
+};
+
+struct imx_sc_pd_soc {
+       const struct imx_sc_pd_range *pd_ranges;
+       u8 num_ranges;
+};
+
+static int imx_con_rsrc;
+
+/* Align with the IMX_SC_PM_PW_MODE_[OFF,STBY,LP,ON] macros */
+static const char * const imx_sc_pm_mode[] = {
+       "IMX_SC_PM_PW_MODE_OFF",
+       "IMX_SC_PM_PW_MODE_STBY",
+       "IMX_SC_PM_PW_MODE_LP",
+       "IMX_SC_PM_PW_MODE_ON"
+};
+
+static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
+       /* LSIO SS */
+       { "pwm", IMX_SC_R_PWM_0, 8, true, 0 },
+       { "gpio", IMX_SC_R_GPIO_0, 8, true, 0 },
+       { "gpt", IMX_SC_R_GPT_0, 5, true, 0 },
+       { "kpp", IMX_SC_R_KPP, 1, false, 0 },
+       { "fspi", IMX_SC_R_FSPI_0, 2, true, 0 },
+       { "mu_a", IMX_SC_R_MU_0A, 14, true, 0 },
+       { "mu_b", IMX_SC_R_MU_5B, 9, true, 5 },
+
+       /* CONN SS */
+       { "usb", IMX_SC_R_USB_0, 2, true, 0 },
+       { "usb0phy", IMX_SC_R_USB_0_PHY, 1, false, 0 },
+       { "usb1phy", IMX_SC_R_USB_1_PHY, 1, false, 0},
+       { "usb2", IMX_SC_R_USB_2, 1, false, 0 },
+       { "usb2phy", IMX_SC_R_USB_2_PHY, 1, false, 0 },
+       { "sdhc", IMX_SC_R_SDHC_0, 3, true, 0 },
+       { "enet", IMX_SC_R_ENET_0, 2, true, 0 },
+       { "nand", IMX_SC_R_NAND, 1, false, 0 },
+       { "mlb", IMX_SC_R_MLB_0, 1, true, 0 },
+
+       /* AUDIO SS */
+       { "audio-pll0", IMX_SC_R_AUDIO_PLL_0, 1, false, 0 },
+       { "audio-pll1", IMX_SC_R_AUDIO_PLL_1, 1, false, 0 },
+       { "audio-clk-0", IMX_SC_R_AUDIO_CLK_0, 1, false, 0 },
+       { "audio-clk-1", IMX_SC_R_AUDIO_CLK_1, 1, false, 0 },
+       { "mclk-out-0", IMX_SC_R_MCLK_OUT_0, 1, false, 0 },
+       { "mclk-out-1", IMX_SC_R_MCLK_OUT_1, 1, false, 0 },
+       { "dma0-ch", IMX_SC_R_DMA_0_CH0, 32, true, 0 },
+       { "dma1-ch", IMX_SC_R_DMA_1_CH0, 16, true, 0 },
+       { "dma2-ch", IMX_SC_R_DMA_2_CH0, 32, true, 0 },
+       { "dma3-ch", IMX_SC_R_DMA_3_CH0, 32, true, 0 },
+       { "asrc0", IMX_SC_R_ASRC_0, 1, false, 0 },
+       { "asrc1", IMX_SC_R_ASRC_1, 1, false, 0 },
+       { "esai0", IMX_SC_R_ESAI_0, 1, false, 0 },
+       { "esai1", IMX_SC_R_ESAI_1, 1, false, 0 },
+       { "spdif0", IMX_SC_R_SPDIF_0, 1, false, 0 },
+       { "spdif1", IMX_SC_R_SPDIF_1, 1, false, 0 },
+       { "sai", IMX_SC_R_SAI_0, 3, true, 0 },
+       { "sai3", IMX_SC_R_SAI_3, 1, false, 0 },
+       { "sai4", IMX_SC_R_SAI_4, 1, false, 0 },
+       { "sai5", IMX_SC_R_SAI_5, 1, false, 0 },
+       { "sai6", IMX_SC_R_SAI_6, 1, false, 0 },
+       { "sai7", IMX_SC_R_SAI_7, 1, false, 0 },
+       { "amix", IMX_SC_R_AMIX, 1, false, 0 },
+       { "mqs0", IMX_SC_R_MQS_0, 1, false, 0 },
+       { "dsp", IMX_SC_R_DSP, 1, false, 0 },
+       { "dsp-ram", IMX_SC_R_DSP_RAM, 1, false, 0 },
+
+       /* DMA SS */
+       { "can", IMX_SC_R_CAN_0, 3, true, 0 },
+       { "ftm", IMX_SC_R_FTM_0, 2, true, 0 },
+       { "lpi2c", IMX_SC_R_I2C_0, 5, true, 0 },
+       { "adc", IMX_SC_R_ADC_0, 2, true, 0 },
+       { "lcd", IMX_SC_R_LCD_0, 1, true, 0 },
+       { "lcd-pll", IMX_SC_R_ELCDIF_PLL, 1, true, 0 },
+       { "lcd0-pwm", IMX_SC_R_LCD_0_PWM_0, 1, true, 0 },
+       { "lpuart", IMX_SC_R_UART_0, 5, true, 0 },
+       { "sim", IMX_SC_R_EMVSIM_0, 2, true, 0 },
+       { "lpspi", IMX_SC_R_SPI_0, 4, true, 0 },
+       { "irqstr_dsp", IMX_SC_R_IRQSTR_DSP, 1, false, 0 },
+
+       /* VPU SS */
+       { "vpu", IMX_SC_R_VPU, 1, false, 0 },
+       { "vpu-pid", IMX_SC_R_VPU_PID0, 8, true, 0 },
+       { "vpu-dec0", IMX_SC_R_VPU_DEC_0, 1, false, 0 },
+       { "vpu-enc0", IMX_SC_R_VPU_ENC_0, 1, false, 0 },
+       { "vpu-enc1", IMX_SC_R_VPU_ENC_1, 1, false, 0 },
+       { "vpu-mu0", IMX_SC_R_VPU_MU_0, 1, false, 0 },
+       { "vpu-mu1", IMX_SC_R_VPU_MU_1, 1, false, 0 },
+       { "vpu-mu2", IMX_SC_R_VPU_MU_2, 1, false, 0 },
+
+       /* GPU SS */
+       { "gpu0-pid", IMX_SC_R_GPU_0_PID0, 4, true, 0 },
+       { "gpu1-pid", IMX_SC_R_GPU_1_PID0, 4, true, 0 },
+
+
+       /* HSIO SS */
+       { "pcie-a", IMX_SC_R_PCIE_A, 1, false, 0 },
+       { "serdes-0", IMX_SC_R_SERDES_0, 1, false, 0 },
+       { "pcie-b", IMX_SC_R_PCIE_B, 1, false, 0 },
+       { "serdes-1", IMX_SC_R_SERDES_1, 1, false, 0 },
+       { "sata-0", IMX_SC_R_SATA_0, 1, false, 0 },
+       { "hsio-gpio", IMX_SC_R_HSIO_GPIO, 1, false, 0 },
+
+       /* MIPI SS */
+       { "mipi0", IMX_SC_R_MIPI_0, 1, false, 0 },
+       { "mipi0-pwm0", IMX_SC_R_MIPI_0_PWM_0, 1, false, 0 },
+       { "mipi0-i2c", IMX_SC_R_MIPI_0_I2C_0, 2, true, 0 },
+
+       { "mipi1", IMX_SC_R_MIPI_1, 1, false, 0 },
+       { "mipi1-pwm0", IMX_SC_R_MIPI_1_PWM_0, 1, false, 0 },
+       { "mipi1-i2c", IMX_SC_R_MIPI_1_I2C_0, 2, true, 0 },
+
+       /* LVDS SS */
+       { "lvds0", IMX_SC_R_LVDS_0, 1, false, 0 },
+       { "lvds0-pwm", IMX_SC_R_LVDS_0_PWM_0, 1, false, 0 },
+       { "lvds0-lpi2c", IMX_SC_R_LVDS_0_I2C_0, 2, true, 0 },
+       { "lvds1", IMX_SC_R_LVDS_1, 1, false, 0 },
+       { "lvds1-pwm", IMX_SC_R_LVDS_1_PWM_0, 1, false, 0 },
+       { "lvds1-lpi2c", IMX_SC_R_LVDS_1_I2C_0, 2, true, 0 },
+
+       { "mipi1", IMX_SC_R_MIPI_1, 1, 0 },
+       { "mipi1-pwm0", IMX_SC_R_MIPI_1_PWM_0, 1, 0 },
+       { "mipi1-i2c", IMX_SC_R_MIPI_1_I2C_0, 2, 1 },
+       { "lvds1", IMX_SC_R_LVDS_1, 1, 0 },
+
+       /* DC SS */
+       { "dc0", IMX_SC_R_DC_0, 1, false, 0 },
+       { "dc0-pll", IMX_SC_R_DC_0_PLL_0, 2, true, 0 },
+       { "dc0-video", IMX_SC_R_DC_0_VIDEO0, 2, true, 0 },
+
+       { "dc1", IMX_SC_R_DC_1, 1, false, 0 },
+       { "dc1-pll", IMX_SC_R_DC_1_PLL_0, 2, true, 0 },
+       { "dc1-video", IMX_SC_R_DC_1_VIDEO0, 2, true, 0 },
+
+       /* CM40 SS */
+       { "cm40-i2c", IMX_SC_R_M4_0_I2C, 1, false, 0 },
+       { "cm40-intmux", IMX_SC_R_M4_0_INTMUX, 1, false, 0 },
+       { "cm40-pid", IMX_SC_R_M4_0_PID0, 5, true, 0},
+       { "cm40-mu-a1", IMX_SC_R_M4_0_MU_1A, 1, false, 0},
+       { "cm40-lpuart", IMX_SC_R_M4_0_UART, 1, false, 0},
+
+       /* CM41 SS */
+       { "cm41-i2c", IMX_SC_R_M4_1_I2C, 1, false, 0 },
+       { "cm41-intmux", IMX_SC_R_M4_1_INTMUX, 1, false, 0 },
+       { "cm41-pid", IMX_SC_R_M4_1_PID0, 5, true, 0},
+       { "cm41-mu-a1", IMX_SC_R_M4_1_MU_1A, 1, false, 0},
+       { "cm41-lpuart", IMX_SC_R_M4_1_UART, 1, false, 0},
+
+       /* CM41 SS */
+       { "cm41_i2c", IMX_SC_R_M4_1_I2C, 1, false, 0 },
+       { "cm41_intmux", IMX_SC_R_M4_1_INTMUX, 1, false, 0 },
+
+       /* DB SS */
+       { "perf", IMX_SC_R_PERF, 1, false, 0},
+
+       /* IMAGE SS */
+       { "img-jpegdec-mp", IMX_SC_R_MJPEG_DEC_MP, 1, false, 0 },
+       { "img-jpegdec-s0", IMX_SC_R_MJPEG_DEC_S0, 4, true, 0 },
+       { "img-jpegenc-mp", IMX_SC_R_MJPEG_ENC_MP, 1, false, 0 },
+       { "img-jpegenc-s0", IMX_SC_R_MJPEG_ENC_S0, 4, true, 0 },
+
+       /* SECO SS */
+       { "seco_mu", IMX_SC_R_SECO_MU_2, 3, true, 2},
+
+       /* V2X SS */
+       { "v2x_mu", IMX_SC_R_V2X_MU_0, 2, true, 0},
+       { "v2x_mu", IMX_SC_R_V2X_MU_2, 1, true, 2},
+       { "v2x_mu", IMX_SC_R_V2X_MU_3, 2, true, 3},
+       { "img-pdma", IMX_SC_R_ISI_CH0, 8, true, 0 },
+       { "img-csi0", IMX_SC_R_CSI_0, 1, false, 0 },
+       { "img-csi0-i2c0", IMX_SC_R_CSI_0_I2C_0, 1, false, 0 },
+       { "img-csi0-pwm0", IMX_SC_R_CSI_0_PWM_0, 1, false, 0 },
+       { "img-csi1", IMX_SC_R_CSI_1, 1, false, 0 },
+       { "img-csi1-i2c0", IMX_SC_R_CSI_1_I2C_0, 1, false, 0 },
+       { "img-csi1-pwm0", IMX_SC_R_CSI_1_PWM_0, 1, false, 0 },
+       { "img-parallel", IMX_SC_R_PI_0, 1, false, 0 },
+       { "img-parallel-i2c0", IMX_SC_R_PI_0_I2C_0, 1, false, 0 },
+       { "img-parallel-pwm0", IMX_SC_R_PI_0_PWM_0, 2, true, 0 },
+       { "img-parallel-pll", IMX_SC_R_PI_0_PLL, 1, false, 0 },
+
+       /* HDMI TX SS */
+       { "hdmi-tx", IMX_SC_R_HDMI, 1, false, 0},
+       { "hdmi-tx-i2s", IMX_SC_R_HDMI_I2S, 1, false, 0},
+       { "hdmi-tx-i2c0", IMX_SC_R_HDMI_I2C_0, 1, false, 0},
+       { "hdmi-tx-pll0", IMX_SC_R_HDMI_PLL_0, 1, false, 0},
+       { "hdmi-tx-pll1", IMX_SC_R_HDMI_PLL_1, 1, false, 0},
+
+       /* HDMI RX SS */
+       { "hdmi-rx", IMX_SC_R_HDMI_RX, 1, false, 0},
+       { "hdmi-rx-pwm", IMX_SC_R_HDMI_RX_PWM_0, 1, false, 0},
+       { "hdmi-rx-i2c0", IMX_SC_R_HDMI_RX_I2C_0, 1, false, 0},
+       { "hdmi-rx-bypass", IMX_SC_R_HDMI_RX_BYPASS, 1, false, 0},
+
+       /* SECURITY SS */
+       { "sec-jr", IMX_SC_R_CAAM_JR2, 2, true, 2},
+
+       /* BOARD SS */
+       { "board", IMX_SC_R_BOARD_R0, 8, true, 0},
+};
+
+static const struct imx_sc_pd_soc imx8qxp_scu_pd = {
+       .pd_ranges = imx8qxp_scu_pd_ranges,
+       .num_ranges = ARRAY_SIZE(imx8qxp_scu_pd_ranges),
+};
+
+static struct imx_sc_ipc *pm_ipc_handle;
+
+static inline struct imx_sc_pm_domain *
+to_imx_sc_pd(struct generic_pm_domain *genpd)
+{
+       return container_of(genpd, struct imx_sc_pm_domain, pd);
+}
+
+static void imx_sc_pd_get_console_rsrc(void)
+{
+       struct of_phandle_args specs;
+       int ret;
+
+       if (!of_stdout)
+               return;
+
+       ret = of_parse_phandle_with_args(of_stdout, "power-domains",
+                                        "#power-domain-cells",
+                                        0, &specs);
+       if (ret)
+               return;
+
+       imx_con_rsrc = specs.args[0];
+}
+
+static int imx_sc_get_pd_power(struct device *dev, u32 rsrc)
+{
+       struct imx_sc_msg_req_get_resource_power_mode msg;
+       struct imx_sc_rpc_msg *hdr = &msg.hdr;
+       int ret;
+
+       hdr->ver = IMX_SC_RPC_VERSION;
+       hdr->svc = IMX_SC_RPC_SVC_PM;
+       hdr->func = IMX_SC_PM_FUNC_GET_RESOURCE_POWER_MODE;
+       hdr->size = 2;
+
+       msg.data.req.resource = rsrc;
+
+       ret = imx_scu_call_rpc(pm_ipc_handle, &msg, true);
+       if (ret)
+               dev_err(dev, "failed to get power resource %d mode, ret %d\n",
+                       rsrc, ret);
+
+       return msg.data.resp.mode;
+}
+
+static int imx_sc_pd_power(struct generic_pm_domain *domain, bool power_on)
+{
+       struct imx_sc_msg_req_set_resource_power_mode msg;
+       struct imx_sc_rpc_msg *hdr = &msg.hdr;
+       struct imx_sc_pm_domain *pd;
+       int ret;
+
+       pd = to_imx_sc_pd(domain);
+
+       hdr->ver = IMX_SC_RPC_VERSION;
+       hdr->svc = IMX_SC_RPC_SVC_PM;
+       hdr->func = IMX_SC_PM_FUNC_SET_RESOURCE_POWER_MODE;
+       hdr->size = 2;
+
+       msg.resource = pd->rsrc;
+       msg.mode = power_on ? IMX_SC_PM_PW_MODE_ON : IMX_SC_PM_PW_MODE_LP;
+
+       /* keep uart console power on for no_console_suspend */
+       if (imx_con_rsrc == pd->rsrc && !console_suspend_enabled && !power_on)
+               return -EBUSY;
+
+       ret = imx_scu_call_rpc(pm_ipc_handle, &msg, true);
+       if (ret)
+               dev_err(&domain->dev, "failed to power %s resource %d ret %d\n",
+                       power_on ? "up" : "off", pd->rsrc, ret);
+
+       return ret;
+}
+
+static int imx_sc_pd_power_on(struct generic_pm_domain *domain)
+{
+       return imx_sc_pd_power(domain, true);
+}
+
+static int imx_sc_pd_power_off(struct generic_pm_domain *domain)
+{
+       return imx_sc_pd_power(domain, false);
+}
+
+static struct generic_pm_domain *imx_scu_pd_xlate(struct of_phandle_args *spec,
+                                                 void *data)
+{
+       struct generic_pm_domain *domain = ERR_PTR(-ENOENT);
+       struct genpd_onecell_data *pd_data = data;
+       unsigned int i;
+
+       for (i = 0; i < pd_data->num_domains; i++) {
+               struct imx_sc_pm_domain *sc_pd;
+
+               sc_pd = to_imx_sc_pd(pd_data->domains[i]);
+               if (sc_pd->rsrc == spec->args[0]) {
+                       domain = &sc_pd->pd;
+                       break;
+               }
+       }
+
+       return domain;
+}
+
+static struct imx_sc_pm_domain *
+imx_scu_add_pm_domain(struct device *dev, int idx,
+                     const struct imx_sc_pd_range *pd_ranges)
+{
+       struct imx_sc_pm_domain *sc_pd;
+       bool is_off;
+       int mode, ret;
+
+       if (!imx_sc_rm_is_resource_owned(pm_ipc_handle, pd_ranges->rsrc + idx))
+               return NULL;
+
+       sc_pd = devm_kzalloc(dev, sizeof(*sc_pd), GFP_KERNEL);
+       if (!sc_pd)
+               return ERR_PTR(-ENOMEM);
+
+       sc_pd->rsrc = pd_ranges->rsrc + idx;
+       sc_pd->pd.power_off = imx_sc_pd_power_off;
+       sc_pd->pd.power_on = imx_sc_pd_power_on;
+
+       if (pd_ranges->postfix)
+               snprintf(sc_pd->name, sizeof(sc_pd->name),
+                        "%s%i", pd_ranges->name, pd_ranges->start_from + idx);
+       else
+               snprintf(sc_pd->name, sizeof(sc_pd->name),
+                        "%s", pd_ranges->name);
+
+       sc_pd->pd.name = sc_pd->name;
+       if (imx_con_rsrc == sc_pd->rsrc)
+               sc_pd->pd.flags = GENPD_FLAG_RPM_ALWAYS_ON;
+
+       mode = imx_sc_get_pd_power(dev, pd_ranges->rsrc + idx);
+       if (mode == IMX_SC_PM_PW_MODE_ON)
+               is_off = false;
+       else
+               is_off = true;
+
+       dev_dbg(dev, "%s : %s\n", sc_pd->name, imx_sc_pm_mode[mode]);
+
+       if (sc_pd->rsrc >= IMX_SC_R_LAST) {
+               dev_warn(dev, "invalid pd %s rsrc id %d found",
+                        sc_pd->name, sc_pd->rsrc);
+
+               devm_kfree(dev, sc_pd);
+               return NULL;
+       }
+
+       ret = pm_genpd_init(&sc_pd->pd, NULL, is_off);
+       if (ret) {
+               dev_warn(dev, "failed to init pd %s rsrc id %d",
+                        sc_pd->name, sc_pd->rsrc);
+               devm_kfree(dev, sc_pd);
+               return NULL;
+       }
+
+       return sc_pd;
+}
+
+static int imx_scu_init_pm_domains(struct device *dev,
+                                   const struct imx_sc_pd_soc *pd_soc)
+{
+       const struct imx_sc_pd_range *pd_ranges = pd_soc->pd_ranges;
+       struct generic_pm_domain **domains;
+       struct genpd_onecell_data *pd_data;
+       struct imx_sc_pm_domain *sc_pd;
+       u32 count = 0;
+       int i, j;
+
+       for (i = 0; i < pd_soc->num_ranges; i++)
+               count += pd_ranges[i].num;
+
+       domains = devm_kcalloc(dev, count, sizeof(*domains), GFP_KERNEL);
+       if (!domains)
+               return -ENOMEM;
+
+       pd_data = devm_kzalloc(dev, sizeof(*pd_data), GFP_KERNEL);
+       if (!pd_data)
+               return -ENOMEM;
+
+       count = 0;
+       for (i = 0; i < pd_soc->num_ranges; i++) {
+               for (j = 0; j < pd_ranges[i].num; j++) {
+                       sc_pd = imx_scu_add_pm_domain(dev, j, &pd_ranges[i]);
+                       if (IS_ERR_OR_NULL(sc_pd))
+                               continue;
+
+                       domains[count++] = &sc_pd->pd;
+                       dev_dbg(dev, "added power domain %s\n", sc_pd->pd.name);
+               }
+       }
+
+       pd_data->domains = domains;
+       pd_data->num_domains = count;
+       pd_data->xlate = imx_scu_pd_xlate;
+
+       of_genpd_add_provider_onecell(dev->of_node, pd_data);
+
+       return 0;
+}
+
+static int imx_sc_pd_probe(struct platform_device *pdev)
+{
+       const struct imx_sc_pd_soc *pd_soc;
+       int ret;
+
+       ret = imx_scu_get_handle(&pm_ipc_handle);
+       if (ret)
+               return ret;
+
+       pd_soc = of_device_get_match_data(&pdev->dev);
+       if (!pd_soc)
+               return -ENODEV;
+
+       imx_sc_pd_get_console_rsrc();
+
+       return imx_scu_init_pm_domains(&pdev->dev, pd_soc);
+}
+
+static const struct of_device_id imx_sc_pd_match[] = {
+       { .compatible = "fsl,imx8qxp-scu-pd", &imx8qxp_scu_pd},
+       { .compatible = "fsl,scu-pd", &imx8qxp_scu_pd},
+       { /* sentinel */ }
+};
+
+static struct platform_driver imx_sc_pd_driver = {
+       .driver = {
+               .name = "imx-scu-pd",
+               .of_match_table = imx_sc_pd_match,
+               .suppress_bind_attrs = true,
+       },
+       .probe = imx_sc_pd_probe,
+};
+builtin_platform_driver(imx_sc_pd_driver);
+
+MODULE_AUTHOR("Dong Aisheng <aisheng.dong@nxp.com>");
+MODULE_DESCRIPTION("IMX SCU Power Domain driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pmdomain/mediatek/Makefile b/drivers/pmdomain/mediatek/Makefile
new file mode 100644 (file)
index 0000000..8cde09e
--- /dev/null
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_MTK_SCPSYS)               += mtk-scpsys.o
+obj-$(CONFIG_MTK_SCPSYS_PM_DOMAINS)    += mtk-pm-domains.o
diff --git a/drivers/pmdomain/mediatek/mt6795-pm-domains.h b/drivers/pmdomain/mediatek/mt6795-pm-domains.h
new file mode 100644 (file)
index 0000000..ef07c9d
--- /dev/null
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MT6795_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT6795_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mt6795-power.h>
+
+/*
+ * MT6795 power domain support
+ */
+
+static const struct scpsys_domain_data scpsys_domain_data_mt6795[] = {
+       [MT6795_POWER_DOMAIN_VDEC] = {
+               .name = "vdec",
+               .sta_mask = PWR_STATUS_VDEC,
+               .ctl_offs = SPM_VDE_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+       },
+       [MT6795_POWER_DOMAIN_VENC] = {
+               .name = "venc",
+               .sta_mask = PWR_STATUS_VENC,
+               .ctl_offs = SPM_VEN_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+       },
+       [MT6795_POWER_DOMAIN_ISP] = {
+               .name = "isp",
+               .sta_mask = PWR_STATUS_ISP,
+               .ctl_offs = SPM_ISP_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(13, 12),
+       },
+       [MT6795_POWER_DOMAIN_MM] = {
+               .name = "mm",
+               .sta_mask = PWR_STATUS_DISP,
+               .ctl_offs = SPM_DIS_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MM_M0 |
+                                              MT8173_TOP_AXI_PROT_EN_MM_M1),
+               },
+       },
+       [MT6795_POWER_DOMAIN_MJC] = {
+               .name = "mjc",
+               .sta_mask = BIT(20),
+               .ctl_offs = 0x298,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+       },
+       [MT6795_POWER_DOMAIN_AUDIO] = {
+               .name = "audio",
+               .sta_mask = PWR_STATUS_AUDIO,
+               .ctl_offs = SPM_AUDIO_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+       },
+       [MT6795_POWER_DOMAIN_MFG_ASYNC] = {
+               .name = "mfg_async",
+               .sta_mask = PWR_STATUS_MFG_ASYNC,
+               .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = 0,
+       },
+       [MT6795_POWER_DOMAIN_MFG_2D] = {
+               .name = "mfg_2d",
+               .sta_mask = PWR_STATUS_MFG_2D,
+               .ctl_offs = SPM_MFG_2D_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(13, 12),
+       },
+       [MT6795_POWER_DOMAIN_MFG] = {
+               .name = "mfg",
+               .sta_mask = PWR_STATUS_MFG,
+               .ctl_offs = SPM_MFG_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(13, 8),
+               .sram_pdn_ack_bits = GENMASK(21, 16),
+               .bp_infracfg = {
+                       BUS_PROT_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MFG_S |
+                                              MT8173_TOP_AXI_PROT_EN_MFG_M0 |
+                                              MT8173_TOP_AXI_PROT_EN_MFG_M1 |
+                                              MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT),
+               },
+       },
+};
+
+static const struct scpsys_soc_data mt6795_scpsys_data = {
+       .domains_data = scpsys_domain_data_mt6795,
+       .num_domains = ARRAY_SIZE(scpsys_domain_data_mt6795),
+};
+
+#endif /* __SOC_MEDIATEK_MT6795_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt8167-pm-domains.h b/drivers/pmdomain/mediatek/mt8167-pm-domains.h
new file mode 100644 (file)
index 0000000..4d6c327
--- /dev/null
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MT8167_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8167_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mt8167-power.h>
+
+#define MT8167_PWR_STATUS_MFG_2D       BIT(24)
+#define MT8167_PWR_STATUS_MFG_ASYNC    BIT(25)
+
+/*
+ * MT8167 power domain support
+ */
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = {
+       [MT8167_POWER_DOMAIN_MM] = {
+               .name = "mm",
+               .sta_mask = PWR_STATUS_DISP,
+               .ctl_offs = SPM_DIS_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_MM_EMI |
+                                              MT8167_TOP_AXI_PROT_EN_MCU_MM),
+               },
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT8167_POWER_DOMAIN_VDEC] = {
+               .name = "vdec",
+               .sta_mask = PWR_STATUS_VDEC,
+               .ctl_offs = SPM_VDE_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT8167_POWER_DOMAIN_ISP] = {
+               .name = "isp",
+               .sta_mask = PWR_STATUS_ISP,
+               .ctl_offs = SPM_ISP_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(13, 12),
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT8167_POWER_DOMAIN_MFG_ASYNC] = {
+               .name = "mfg_async",
+               .sta_mask = MT8167_PWR_STATUS_MFG_ASYNC,
+               .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = 0,
+               .sram_pdn_ack_bits = 0,
+               .bp_infracfg = {
+                       BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_MCU_MFG |
+                                              MT8167_TOP_AXI_PROT_EN_MFG_EMI),
+               },
+       },
+       [MT8167_POWER_DOMAIN_MFG_2D] = {
+               .name = "mfg_2d",
+               .sta_mask = MT8167_PWR_STATUS_MFG_2D,
+               .ctl_offs = SPM_MFG_2D_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+       },
+       [MT8167_POWER_DOMAIN_MFG] = {
+               .name = "mfg",
+               .sta_mask = PWR_STATUS_MFG,
+               .ctl_offs = SPM_MFG_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+       },
+       [MT8167_POWER_DOMAIN_CONN] = {
+               .name = "conn",
+               .sta_mask = PWR_STATUS_CONN,
+               .ctl_offs = SPM_CONN_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = 0,
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+               .bp_infracfg = {
+                       BUS_PROT_UPDATE_TOPAXI(MT8167_TOP_AXI_PROT_EN_CONN_EMI |
+                                              MT8167_TOP_AXI_PROT_EN_CONN_MCU |
+                                              MT8167_TOP_AXI_PROT_EN_MCU_CONN),
+               },
+       },
+};
+
+static const struct scpsys_soc_data mt8167_scpsys_data = {
+       .domains_data = scpsys_domain_data_mt8167,
+       .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8167),
+};
+
+#endif /* __SOC_MEDIATEK_MT8167_PM_DOMAINS_H */
+
diff --git a/drivers/pmdomain/mediatek/mt8173-pm-domains.h b/drivers/pmdomain/mediatek/mt8173-pm-domains.h
new file mode 100644 (file)
index 0000000..1a5dc63
--- /dev/null
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MT8173_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8173_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mt8173-power.h>
+
+/*
+ * MT8173 power domain support
+ */
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = {
+       [MT8173_POWER_DOMAIN_VDEC] = {
+               .name = "vdec",
+               .sta_mask = PWR_STATUS_VDEC,
+               .ctl_offs = SPM_VDE_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+       },
+       [MT8173_POWER_DOMAIN_VENC] = {
+               .name = "venc",
+               .sta_mask = PWR_STATUS_VENC,
+               .ctl_offs = SPM_VEN_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+       },
+       [MT8173_POWER_DOMAIN_ISP] = {
+               .name = "isp",
+               .sta_mask = PWR_STATUS_ISP,
+               .ctl_offs = SPM_ISP_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(13, 12),
+       },
+       [MT8173_POWER_DOMAIN_MM] = {
+               .name = "mm",
+               .sta_mask = PWR_STATUS_DISP,
+               .ctl_offs = SPM_DIS_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MM_M0 |
+                                              MT8173_TOP_AXI_PROT_EN_MM_M1),
+               },
+       },
+       [MT8173_POWER_DOMAIN_VENC_LT] = {
+               .name = "venc_lt",
+               .sta_mask = PWR_STATUS_VENC_LT,
+               .ctl_offs = SPM_VEN2_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+       },
+       [MT8173_POWER_DOMAIN_AUDIO] = {
+               .name = "audio",
+               .sta_mask = PWR_STATUS_AUDIO,
+               .ctl_offs = SPM_AUDIO_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+       },
+       [MT8173_POWER_DOMAIN_USB] = {
+               .name = "usb",
+               .sta_mask = PWR_STATUS_USB,
+               .ctl_offs = SPM_USB_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT8173_POWER_DOMAIN_MFG_ASYNC] = {
+               .name = "mfg_async",
+               .sta_mask = PWR_STATUS_MFG_ASYNC,
+               .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = 0,
+               .caps = MTK_SCPD_DOMAIN_SUPPLY,
+       },
+       [MT8173_POWER_DOMAIN_MFG_2D] = {
+               .name = "mfg_2d",
+               .sta_mask = PWR_STATUS_MFG_2D,
+               .ctl_offs = SPM_MFG_2D_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(13, 12),
+       },
+       [MT8173_POWER_DOMAIN_MFG] = {
+               .name = "mfg",
+               .sta_mask = PWR_STATUS_MFG,
+               .ctl_offs = SPM_MFG_PWR_CON,
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
+               .sram_pdn_bits = GENMASK(13, 8),
+               .sram_pdn_ack_bits = GENMASK(21, 16),
+               .bp_infracfg = {
+                       BUS_PROT_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MFG_S |
+                                              MT8173_TOP_AXI_PROT_EN_MFG_M0 |
+                                              MT8173_TOP_AXI_PROT_EN_MFG_M1 |
+                                              MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT),
+               },
+       },
+};
+
+static const struct scpsys_soc_data mt8173_scpsys_data = {
+       .domains_data = scpsys_domain_data_mt8173,
+       .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8173),
+};
+
+#endif /* __SOC_MEDIATEK_MT8173_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt8183-pm-domains.h b/drivers/pmdomain/mediatek/mt8183-pm-domains.h
new file mode 100644 (file)
index 0000000..99de67f
--- /dev/null
@@ -0,0 +1,266 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MT8183_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8183_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mt8183-power.h>
+
+/*
+ * MT8183 power domain support
+ */
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = {
+       [MT8183_POWER_DOMAIN_AUDIO] = {
+               .name = "audio",
+               .sta_mask = PWR_STATUS_AUDIO,
+               .ctl_offs = 0x0314,
+               .pwr_sta_offs = 0x0180,
+               .pwr_sta2nd_offs = 0x0184,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+       },
+       [MT8183_POWER_DOMAIN_CONN] = {
+               .name = "conn",
+               .sta_mask = PWR_STATUS_CONN,
+               .ctl_offs = 0x032c,
+               .pwr_sta_offs = 0x0180,
+               .pwr_sta2nd_offs = 0x0184,
+               .sram_pdn_bits = 0,
+               .sram_pdn_ack_bits = 0,
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_CONN, MT8183_TOP_AXI_PROT_EN_SET,
+                                   MT8183_TOP_AXI_PROT_EN_CLR, MT8183_TOP_AXI_PROT_EN_STA1),
+               },
+       },
+       [MT8183_POWER_DOMAIN_MFG_ASYNC] = {
+               .name = "mfg_async",
+               .sta_mask = PWR_STATUS_MFG_ASYNC,
+               .ctl_offs = 0x0334,
+               .pwr_sta_offs = 0x0180,
+               .pwr_sta2nd_offs = 0x0184,
+               .sram_pdn_bits = 0,
+               .sram_pdn_ack_bits = 0,
+               .caps = MTK_SCPD_DOMAIN_SUPPLY,
+       },
+       [MT8183_POWER_DOMAIN_MFG] = {
+               .name = "mfg",
+               .sta_mask = PWR_STATUS_MFG,
+               .ctl_offs = 0x0338,
+               .pwr_sta_offs = 0x0180,
+               .pwr_sta2nd_offs = 0x0184,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .caps = MTK_SCPD_DOMAIN_SUPPLY,
+       },
+       [MT8183_POWER_DOMAIN_MFG_CORE0] = {
+               .name = "mfg_core0",
+               .sta_mask = BIT(7),
+               .ctl_offs = 0x034c,
+               .pwr_sta_offs = 0x0180,
+               .pwr_sta2nd_offs = 0x0184,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+       },
+       [MT8183_POWER_DOMAIN_MFG_CORE1] = {
+               .name = "mfg_core1",
+               .sta_mask = BIT(20),
+               .ctl_offs = 0x0310,
+               .pwr_sta_offs = 0x0180,
+               .pwr_sta2nd_offs = 0x0184,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+       },
+       [MT8183_POWER_DOMAIN_MFG_2D] = {
+               .name = "mfg_2d",
+               .sta_mask = PWR_STATUS_MFG_2D,
+               .ctl_offs = 0x0348,
+               .pwr_sta_offs = 0x0180,
+               .pwr_sta2nd_offs = 0x0184,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_1_MFG, MT8183_TOP_AXI_PROT_EN_1_SET,
+                                   MT8183_TOP_AXI_PROT_EN_1_CLR, MT8183_TOP_AXI_PROT_EN_STA1_1),
+                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MFG, MT8183_TOP_AXI_PROT_EN_SET,
+                                   MT8183_TOP_AXI_PROT_EN_CLR, MT8183_TOP_AXI_PROT_EN_STA1),
+               },
+       },
+       [MT8183_POWER_DOMAIN_DISP] = {
+               .name = "disp",
+               .sta_mask = PWR_STATUS_DISP,
+               .ctl_offs = 0x030c,
+               .pwr_sta_offs = 0x0180,
+               .pwr_sta2nd_offs = 0x0184,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_1_DISP, MT8183_TOP_AXI_PROT_EN_1_SET,
+                                   MT8183_TOP_AXI_PROT_EN_1_CLR, MT8183_TOP_AXI_PROT_EN_STA1_1),
+                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_DISP, MT8183_TOP_AXI_PROT_EN_SET,
+                                   MT8183_TOP_AXI_PROT_EN_CLR, MT8183_TOP_AXI_PROT_EN_STA1),
+               },
+               .bp_smi = {
+                       BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_DISP,
+                                   MT8183_SMI_COMMON_CLAMP_EN_SET,
+                                   MT8183_SMI_COMMON_CLAMP_EN_CLR,
+                                   MT8183_SMI_COMMON_CLAMP_EN),
+               },
+       },
+       [MT8183_POWER_DOMAIN_CAM] = {
+               .name = "cam",
+               .sta_mask = BIT(25),
+               .ctl_offs = 0x0344,
+               .pwr_sta_offs = 0x0180,
+               .pwr_sta2nd_offs = 0x0184,
+               .sram_pdn_bits = GENMASK(9, 8),
+               .sram_pdn_ack_bits = GENMASK(13, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MM_CAM, MT8183_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8183_TOP_AXI_PROT_EN_MM_CLR, MT8183_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_CAM, MT8183_TOP_AXI_PROT_EN_SET,
+                                   MT8183_TOP_AXI_PROT_EN_CLR, MT8183_TOP_AXI_PROT_EN_STA1),
+                       BUS_PROT_WR_IGN(MT8183_TOP_AXI_PROT_EN_MM_CAM_2ND,
+                                       MT8183_TOP_AXI_PROT_EN_MM_SET,
+                                       MT8183_TOP_AXI_PROT_EN_MM_CLR,
+                                       MT8183_TOP_AXI_PROT_EN_MM_STA1),
+               },
+               .bp_smi = {
+                       BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_CAM,
+                                   MT8183_SMI_COMMON_CLAMP_EN_SET,
+                                   MT8183_SMI_COMMON_CLAMP_EN_CLR,
+                                   MT8183_SMI_COMMON_CLAMP_EN),
+               },
+       },
+       [MT8183_POWER_DOMAIN_ISP] = {
+               .name = "isp",
+               .sta_mask = PWR_STATUS_ISP,
+               .ctl_offs = 0x0308,
+               .pwr_sta_offs = 0x0180,
+               .pwr_sta2nd_offs = 0x0184,
+               .sram_pdn_bits = GENMASK(9, 8),
+               .sram_pdn_ack_bits = GENMASK(13, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MM_ISP,
+                                   MT8183_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8183_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8183_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR_IGN(MT8183_TOP_AXI_PROT_EN_MM_ISP_2ND,
+                                       MT8183_TOP_AXI_PROT_EN_MM_SET,
+                                       MT8183_TOP_AXI_PROT_EN_MM_CLR,
+                                       MT8183_TOP_AXI_PROT_EN_MM_STA1),
+               },
+               .bp_smi = {
+                       BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_ISP,
+                                   MT8183_SMI_COMMON_CLAMP_EN_SET,
+                                   MT8183_SMI_COMMON_CLAMP_EN_CLR,
+                                   MT8183_SMI_COMMON_CLAMP_EN),
+               },
+       },
+       [MT8183_POWER_DOMAIN_VDEC] = {
+               .name = "vdec",
+               .sta_mask = BIT(31),
+               .ctl_offs = 0x0300,
+               .pwr_sta_offs = 0x0180,
+               .pwr_sta2nd_offs = 0x0184,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_smi = {
+                       BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_VDEC,
+                                   MT8183_SMI_COMMON_CLAMP_EN_SET,
+                                   MT8183_SMI_COMMON_CLAMP_EN_CLR,
+                                   MT8183_SMI_COMMON_CLAMP_EN),
+               },
+       },
+       [MT8183_POWER_DOMAIN_VENC] = {
+               .name = "venc",
+               .sta_mask = PWR_STATUS_VENC,
+               .ctl_offs = 0x0304,
+               .pwr_sta_offs = 0x0180,
+               .pwr_sta2nd_offs = 0x0184,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .bp_smi = {
+                       BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_VENC,
+                                   MT8183_SMI_COMMON_CLAMP_EN_SET,
+                                   MT8183_SMI_COMMON_CLAMP_EN_CLR,
+                                   MT8183_SMI_COMMON_CLAMP_EN),
+               },
+       },
+       [MT8183_POWER_DOMAIN_VPU_TOP] = {
+               .name = "vpu_top",
+               .sta_mask = BIT(26),
+               .ctl_offs = 0x0324,
+               .pwr_sta_offs = 0x0180,
+               .pwr_sta2nd_offs = 0x0184,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MM_VPU_TOP,
+                                   MT8183_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8183_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8183_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_VPU_TOP,
+                                   MT8183_TOP_AXI_PROT_EN_SET,
+                                   MT8183_TOP_AXI_PROT_EN_CLR,
+                                   MT8183_TOP_AXI_PROT_EN_STA1),
+                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MM_VPU_TOP_2ND,
+                                   MT8183_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8183_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8183_TOP_AXI_PROT_EN_MM_STA1),
+               },
+               .bp_smi = {
+                       BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_VPU_TOP,
+                                   MT8183_SMI_COMMON_CLAMP_EN_SET,
+                                   MT8183_SMI_COMMON_CLAMP_EN_CLR,
+                                   MT8183_SMI_COMMON_CLAMP_EN),
+               },
+       },
+       [MT8183_POWER_DOMAIN_VPU_CORE0] = {
+               .name = "vpu_core0",
+               .sta_mask = BIT(27),
+               .ctl_offs = 0x33c,
+               .pwr_sta_offs = 0x0180,
+               .pwr_sta2nd_offs = 0x0184,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(13, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE0,
+                                   MT8183_TOP_AXI_PROT_EN_MCU_SET,
+                                   MT8183_TOP_AXI_PROT_EN_MCU_CLR,
+                                   MT8183_TOP_AXI_PROT_EN_MCU_STA1),
+                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE0_2ND,
+                                   MT8183_TOP_AXI_PROT_EN_MCU_SET,
+                                   MT8183_TOP_AXI_PROT_EN_MCU_CLR,
+                                   MT8183_TOP_AXI_PROT_EN_MCU_STA1),
+               },
+               .caps = MTK_SCPD_SRAM_ISO,
+       },
+       [MT8183_POWER_DOMAIN_VPU_CORE1] = {
+               .name = "vpu_core1",
+               .sta_mask = BIT(28),
+               .ctl_offs = 0x0340,
+               .pwr_sta_offs = 0x0180,
+               .pwr_sta2nd_offs = 0x0184,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(13, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE1,
+                                   MT8183_TOP_AXI_PROT_EN_MCU_SET,
+                                   MT8183_TOP_AXI_PROT_EN_MCU_CLR,
+                                   MT8183_TOP_AXI_PROT_EN_MCU_STA1),
+                       BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE1_2ND,
+                                   MT8183_TOP_AXI_PROT_EN_MCU_SET,
+                                   MT8183_TOP_AXI_PROT_EN_MCU_CLR,
+                                   MT8183_TOP_AXI_PROT_EN_MCU_STA1),
+               },
+               .caps = MTK_SCPD_SRAM_ISO,
+       },
+};
+
+static const struct scpsys_soc_data mt8183_scpsys_data = {
+       .domains_data = scpsys_domain_data_mt8183,
+       .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8183),
+};
+
+#endif /* __SOC_MEDIATEK_MT8183_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt8186-pm-domains.h b/drivers/pmdomain/mediatek/mt8186-pm-domains.h
new file mode 100644 (file)
index 0000000..fce86f7
--- /dev/null
@@ -0,0 +1,342 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+ */
+
+#ifndef __SOC_MEDIATEK_MT8186_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8186_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mt8186-power.h>
+
+/*
+ * MT8186 power domain support
+ */
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8186[] = {
+       [MT8186_POWER_DOMAIN_MFG0] = {
+               .name = "mfg0",
+               .sta_mask = BIT(2),
+               .ctl_offs = 0x308,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
+       },
+       [MT8186_POWER_DOMAIN_MFG1] = {
+               .name = "mfg1",
+               .sta_mask = BIT(3),
+               .ctl_offs = 0x30c,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_MFG1_STEP1,
+                               MT8186_TOP_AXI_PROT_EN_1_SET,
+                               MT8186_TOP_AXI_PROT_EN_1_CLR,
+                               MT8186_TOP_AXI_PROT_EN_1_STA),
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_MFG1_STEP2,
+                               MT8186_TOP_AXI_PROT_EN_SET,
+                               MT8186_TOP_AXI_PROT_EN_CLR,
+                               MT8186_TOP_AXI_PROT_EN_STA),
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_MFG1_STEP3,
+                               MT8186_TOP_AXI_PROT_EN_SET,
+                               MT8186_TOP_AXI_PROT_EN_CLR,
+                               MT8186_TOP_AXI_PROT_EN_STA),
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_MFG1_STEP4,
+                               MT8186_TOP_AXI_PROT_EN_1_SET,
+                               MT8186_TOP_AXI_PROT_EN_1_CLR,
+                               MT8186_TOP_AXI_PROT_EN_1_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
+       },
+       [MT8186_POWER_DOMAIN_MFG2] = {
+               .name = "mfg2",
+               .sta_mask = BIT(4),
+               .ctl_offs = 0x310,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8186_POWER_DOMAIN_MFG3] = {
+               .name = "mfg3",
+               .sta_mask = BIT(5),
+               .ctl_offs = 0x314,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8186_POWER_DOMAIN_SSUSB] = {
+               .name = "ssusb",
+               .sta_mask = BIT(20),
+               .ctl_offs = 0x9F0,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT8186_POWER_DOMAIN_SSUSB_P1] = {
+               .name = "ssusb_p1",
+               .sta_mask = BIT(19),
+               .ctl_offs = 0x9F4,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT8186_POWER_DOMAIN_DIS] = {
+               .name = "dis",
+               .sta_mask = BIT(21),
+               .ctl_offs = 0x354,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_DIS_STEP1,
+                               MT8186_TOP_AXI_PROT_EN_1_SET,
+                               MT8186_TOP_AXI_PROT_EN_1_CLR,
+                               MT8186_TOP_AXI_PROT_EN_1_STA),
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_DIS_STEP2,
+                               MT8186_TOP_AXI_PROT_EN_SET,
+                               MT8186_TOP_AXI_PROT_EN_CLR,
+                               MT8186_TOP_AXI_PROT_EN_STA),
+               },
+       },
+       [MT8186_POWER_DOMAIN_IMG] = {
+               .name = "img",
+               .sta_mask = BIT(13),
+               .ctl_offs = 0x334,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_IMG_STEP1,
+                               MT8186_TOP_AXI_PROT_EN_1_SET,
+                               MT8186_TOP_AXI_PROT_EN_1_CLR,
+                               MT8186_TOP_AXI_PROT_EN_1_STA),
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_IMG_STEP2,
+                               MT8186_TOP_AXI_PROT_EN_1_SET,
+                               MT8186_TOP_AXI_PROT_EN_1_CLR,
+                               MT8186_TOP_AXI_PROT_EN_1_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8186_POWER_DOMAIN_IMG2] = {
+               .name = "img2",
+               .sta_mask = BIT(14),
+               .ctl_offs = 0x338,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8186_POWER_DOMAIN_IPE] = {
+               .name = "ipe",
+               .sta_mask = BIT(15),
+               .ctl_offs = 0x33C,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_IPE_STEP1,
+                               MT8186_TOP_AXI_PROT_EN_1_SET,
+                               MT8186_TOP_AXI_PROT_EN_1_CLR,
+                               MT8186_TOP_AXI_PROT_EN_1_STA),
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_IPE_STEP2,
+                               MT8186_TOP_AXI_PROT_EN_1_SET,
+                               MT8186_TOP_AXI_PROT_EN_1_CLR,
+                               MT8186_TOP_AXI_PROT_EN_1_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8186_POWER_DOMAIN_CAM] = {
+               .name = "cam",
+               .sta_mask = BIT(23),
+               .ctl_offs = 0x35C,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_CAM_STEP1,
+                               MT8186_TOP_AXI_PROT_EN_1_SET,
+                               MT8186_TOP_AXI_PROT_EN_1_CLR,
+                               MT8186_TOP_AXI_PROT_EN_1_STA),
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_CAM_STEP2,
+                               MT8186_TOP_AXI_PROT_EN_1_SET,
+                               MT8186_TOP_AXI_PROT_EN_1_CLR,
+                               MT8186_TOP_AXI_PROT_EN_1_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8186_POWER_DOMAIN_CAM_RAWA] = {
+               .name = "cam_rawa",
+               .sta_mask = BIT(24),
+               .ctl_offs = 0x360,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8186_POWER_DOMAIN_CAM_RAWB] = {
+               .name = "cam_rawb",
+               .sta_mask = BIT(25),
+               .ctl_offs = 0x364,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8186_POWER_DOMAIN_VENC] = {
+               .name = "venc",
+               .sta_mask = BIT(18),
+               .ctl_offs = 0x348,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_VENC_STEP1,
+                               MT8186_TOP_AXI_PROT_EN_1_SET,
+                               MT8186_TOP_AXI_PROT_EN_1_CLR,
+                               MT8186_TOP_AXI_PROT_EN_1_STA),
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_VENC_STEP2,
+                               MT8186_TOP_AXI_PROT_EN_1_SET,
+                               MT8186_TOP_AXI_PROT_EN_1_CLR,
+                               MT8186_TOP_AXI_PROT_EN_1_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8186_POWER_DOMAIN_VDEC] = {
+               .name = "vdec",
+               .sta_mask = BIT(16),
+               .ctl_offs = 0x340,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_VDEC_STEP1,
+                               MT8186_TOP_AXI_PROT_EN_1_SET,
+                               MT8186_TOP_AXI_PROT_EN_1_CLR,
+                               MT8186_TOP_AXI_PROT_EN_1_STA),
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_VDEC_STEP2,
+                               MT8186_TOP_AXI_PROT_EN_1_SET,
+                               MT8186_TOP_AXI_PROT_EN_1_CLR,
+                               MT8186_TOP_AXI_PROT_EN_1_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8186_POWER_DOMAIN_WPE] = {
+               .name = "wpe",
+               .sta_mask = BIT(0),
+               .ctl_offs = 0x3F8,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_2_WPE_STEP1,
+                               MT8186_TOP_AXI_PROT_EN_2_SET,
+                               MT8186_TOP_AXI_PROT_EN_2_CLR,
+                               MT8186_TOP_AXI_PROT_EN_2_STA),
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_2_WPE_STEP2,
+                               MT8186_TOP_AXI_PROT_EN_2_SET,
+                               MT8186_TOP_AXI_PROT_EN_2_CLR,
+                               MT8186_TOP_AXI_PROT_EN_2_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8186_POWER_DOMAIN_CONN_ON] = {
+               .name = "conn_on",
+               .sta_mask = BIT(1),
+               .ctl_offs = 0x304,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .bp_infracfg = {
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_1_CONN_ON_STEP1,
+                               MT8186_TOP_AXI_PROT_EN_1_SET,
+                               MT8186_TOP_AXI_PROT_EN_1_CLR,
+                               MT8186_TOP_AXI_PROT_EN_1_STA),
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP2,
+                               MT8186_TOP_AXI_PROT_EN_SET,
+                               MT8186_TOP_AXI_PROT_EN_CLR,
+                               MT8186_TOP_AXI_PROT_EN_STA),
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP3,
+                               MT8186_TOP_AXI_PROT_EN_SET,
+                               MT8186_TOP_AXI_PROT_EN_CLR,
+                               MT8186_TOP_AXI_PROT_EN_STA),
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_CONN_ON_STEP4,
+                               MT8186_TOP_AXI_PROT_EN_SET,
+                               MT8186_TOP_AXI_PROT_EN_CLR,
+                               MT8186_TOP_AXI_PROT_EN_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT8186_POWER_DOMAIN_CSIRX_TOP] = {
+               .name = "csirx_top",
+               .sta_mask = BIT(6),
+               .ctl_offs = 0x318,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8186_POWER_DOMAIN_ADSP_AO] = {
+               .name = "adsp_ao",
+               .sta_mask = BIT(17),
+               .ctl_offs = 0x9FC,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+       },
+       [MT8186_POWER_DOMAIN_ADSP_INFRA] = {
+               .name = "adsp_infra",
+               .sta_mask = BIT(10),
+               .ctl_offs = 0x9F8,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+       },
+       [MT8186_POWER_DOMAIN_ADSP_TOP] = {
+               .name = "adsp_top",
+               .sta_mask = BIT(31),
+               .ctl_offs = 0x3E4,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_3_ADSP_TOP_STEP1,
+                               MT8186_TOP_AXI_PROT_EN_3_SET,
+                               MT8186_TOP_AXI_PROT_EN_3_CLR,
+                               MT8186_TOP_AXI_PROT_EN_3_STA),
+                       BUS_PROT_WR_IGN(MT8186_TOP_AXI_PROT_EN_3_ADSP_TOP_STEP2,
+                               MT8186_TOP_AXI_PROT_EN_3_SET,
+                               MT8186_TOP_AXI_PROT_EN_3_CLR,
+                               MT8186_TOP_AXI_PROT_EN_3_STA),
+               },
+               .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_ACTIVE_WAKEUP,
+       },
+};
+
+static const struct scpsys_soc_data mt8186_scpsys_data = {
+       .domains_data = scpsys_domain_data_mt8186,
+       .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8186),
+};
+
+#endif /* __SOC_MEDIATEK_MT8186_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt8188-pm-domains.h b/drivers/pmdomain/mediatek/mt8188-pm-domains.h
new file mode 100644 (file)
index 0000000..0692cb4
--- /dev/null
@@ -0,0 +1,623 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Garmin Chang <garmin.chang@mediatek.com>
+ */
+
+#ifndef __SOC_MEDIATEK_MT8188_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8188_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mediatek,mt8188-power.h>
+
+/*
+ * MT8188 power domain support
+ */
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8188[] = {
+       [MT8188_POWER_DOMAIN_MFG0] = {
+               .name = "mfg0",
+               .sta_mask = BIT(1),
+               .ctl_offs = 0x300,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
+       },
+       [MT8188_POWER_DOMAIN_MFG1] = {
+               .name = "mfg1",
+               .sta_mask = BIT(2),
+               .ctl_offs = 0x304,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MFG1_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_SET,
+                                   MT8188_TOP_AXI_PROT_EN_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_MFG1_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_2_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_1_MFG1_STEP3,
+                                   MT8188_TOP_AXI_PROT_EN_1_SET,
+                                   MT8188_TOP_AXI_PROT_EN_1_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_1_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_MFG1_STEP4,
+                                   MT8188_TOP_AXI_PROT_EN_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_2_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MFG1_STEP5,
+                                   MT8188_TOP_AXI_PROT_EN_SET,
+                                   MT8188_TOP_AXI_PROT_EN_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MFG1_STEP6,
+                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
+       },
+       [MT8188_POWER_DOMAIN_MFG2] = {
+               .name = "mfg2",
+               .sta_mask = BIT(3),
+               .ctl_offs = 0x308,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_MFG3] = {
+               .name = "mfg3",
+               .sta_mask = BIT(4),
+               .ctl_offs = 0x30C,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_MFG4] = {
+               .name = "mfg4",
+               .sta_mask = BIT(5),
+               .ctl_offs = 0x310,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_PEXTP_MAC_P0] = {
+               .name = "pextp_mac_p0",
+               .sta_mask = BIT(10),
+               .ctl_offs = 0x324,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_PEXTP_MAC_P0_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_SET,
+                                   MT8188_TOP_AXI_PROT_EN_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_PEXTP_MAC_P0_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
+                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_PEXTP_PHY_TOP] = {
+               .name = "pextp_phy_top",
+               .sta_mask = BIT(12),
+               .ctl_offs = 0x328,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_CSIRX_TOP] = {
+               .name = "pextp_csirx_top",
+               .sta_mask = BIT(17),
+               .ctl_offs = 0x3C4,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_ETHER] = {
+               .name = "ether",
+               .sta_mask = BIT(1),
+               .ctl_offs = 0x338,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_ETHER_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
+                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT8188_POWER_DOMAIN_HDMI_TX] = {
+               .name = "hdmi_tx",
+               .sta_mask = BIT(18),
+               .ctl_offs = 0x37C,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_HDMI_TX_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
+                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT8188_POWER_DOMAIN_ADSP_AO] = {
+               .name = "adsp_ao",
+               .sta_mask = BIT(10),
+               .ctl_offs = 0x35C,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_AO_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_2_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_AO_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_2_STA),
+               },
+               .caps = MTK_SCPD_ALWAYS_ON,
+       },
+       [MT8188_POWER_DOMAIN_ADSP_INFRA] = {
+               .name = "adsp_infra",
+               .sta_mask = BIT(9),
+               .ctl_offs = 0x358,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_INFRA_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_2_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_INFRA_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_2_STA),
+               },
+               .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_ALWAYS_ON,
+       },
+       [MT8188_POWER_DOMAIN_ADSP] = {
+               .name = "adsp",
+               .sta_mask = BIT(8),
+               .ctl_offs = 0x354,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_2_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_ADSP_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_2_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_SRAM_ISO | MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT8188_POWER_DOMAIN_AUDIO] = {
+               .name = "audio",
+               .sta_mask = BIT(6),
+               .ctl_offs = 0x34C,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_2_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_2_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT8188_POWER_DOMAIN_AUDIO_ASRC] = {
+               .name = "audio_asrc",
+               .sta_mask = BIT(7),
+               .ctl_offs = 0x350,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_ASRC_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_2_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_AUDIO_ASRC_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_2_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_VPPSYS0] = {
+               .name = "vppsys0",
+               .sta_mask = BIT(11),
+               .ctl_offs = 0x360,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_VPPSYS0_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_SET,
+                                   MT8188_TOP_AXI_PROT_EN_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS0_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_VPPSYS0_STEP3,
+                                   MT8188_TOP_AXI_PROT_EN_SET,
+                                   MT8188_TOP_AXI_PROT_EN_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS0_STEP4,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VPPSYS0_STEP5,
+                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA),
+               },
+       },
+       [MT8188_POWER_DOMAIN_VDOSYS0] = {
+               .name = "vdosys0",
+               .sta_mask = BIT(13),
+               .ctl_offs = 0x368,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDOSYS0_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_VDOSYS0_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_SET,
+                                   MT8188_TOP_AXI_PROT_EN_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VDOSYS0_STEP3,
+                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA),
+               },
+       },
+       [MT8188_POWER_DOMAIN_VDOSYS1] = {
+               .name = "vdosys1",
+               .sta_mask = BIT(14),
+               .ctl_offs = 0x36C,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDOSYS1_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDOSYS1_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VDOSYS1_STEP3,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+               },
+       },
+       [MT8188_POWER_DOMAIN_DP_TX] = {
+               .name = "dp_tx",
+               .sta_mask = BIT(16),
+               .ctl_offs = 0x374,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_DP_TX_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
+                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_EDP_TX] = {
+               .name = "edp_tx",
+               .sta_mask = BIT(17),
+               .ctl_offs = 0x378,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_EDP_TX_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_SET,
+                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_INFRA_VDNR_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_VPPSYS1] = {
+               .name = "vppsys1",
+               .sta_mask = BIT(12),
+               .ctl_offs = 0x364,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VPPSYS1_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VPPSYS1_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VPPSYS1_STEP3,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+               },
+       },
+       [MT8188_POWER_DOMAIN_WPE] = {
+               .name = "wpe",
+               .sta_mask = BIT(15),
+               .ctl_offs = 0x370,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_WPE_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_WPE_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_VDEC0] = {
+               .name = "vdec0",
+               .sta_mask = BIT(19),
+               .ctl_offs = 0x380,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDEC0_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VDEC0_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_VDEC1] = {
+               .name = "vdec1",
+               .sta_mask = BIT(20),
+               .ctl_offs = 0x384,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDEC1_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VDEC1_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_VENC] = {
+               .name = "venc",
+               .sta_mask = BIT(22),
+               .ctl_offs = 0x38C,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VENC_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_VENC_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_VENC_STEP3,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_IMG_VCORE] = {
+               .name = "vcore",
+               .sta_mask = BIT(28),
+               .ctl_offs = 0x3A4,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_IMG_VCORE_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_IMG_VCORE_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_IMG_VCORE_STEP3,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
+       },
+       [MT8188_POWER_DOMAIN_IMG_MAIN] = {
+               .name = "img_main",
+               .sta_mask = BIT(29),
+               .ctl_offs = 0x3A8,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_IMG_MAIN_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_IMG_MAIN_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_DIP] = {
+               .name = "dip",
+               .sta_mask = BIT(30),
+               .ctl_offs = 0x3AC,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_IPE] = {
+               .name = "ipe",
+               .sta_mask = BIT(31),
+               .ctl_offs = 0x3B0,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_CAM_VCORE] = {
+               .name = "cam_vcore",
+               .sta_mask = BIT(27),
+               .ctl_offs = 0x3A0,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_CAM_VCORE_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_CAM_VCORE_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_2_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_1_CAM_VCORE_STEP3,
+                                   MT8188_TOP_AXI_PROT_EN_1_SET,
+                                   MT8188_TOP_AXI_PROT_EN_1_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_1_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_CAM_VCORE_STEP4,
+                                   MT8188_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_CAM_VCORE_STEP5,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
+       },
+       [MT8188_POWER_DOMAIN_CAM_MAIN] = {
+               .name = "cam_main",
+               .sta_mask = BIT(24),
+               .ctl_offs = 0x394,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_CAM_MAIN_STEP1,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_CAM_MAIN_STEP2,
+                                   MT8188_TOP_AXI_PROT_EN_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_2_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_MM_2_CAM_MAIN_STEP3,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_MM_2_STA),
+                       BUS_PROT_WR(MT8188_TOP_AXI_PROT_EN_2_CAM_MAIN_STEP4,
+                                   MT8188_TOP_AXI_PROT_EN_2_SET,
+                                   MT8188_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8188_TOP_AXI_PROT_EN_2_STA),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_CAM_SUBA] = {
+               .name = "cam_suba",
+               .sta_mask = BIT(25),
+               .ctl_offs = 0x398,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8188_POWER_DOMAIN_CAM_SUBB] = {
+               .name = "cam_subb",
+               .sta_mask = BIT(26),
+               .ctl_offs = 0x39C,
+               .pwr_sta_offs = 0x16C,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = BIT(8),
+               .sram_pdn_ack_bits = BIT(12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+};
+
+static const struct scpsys_soc_data mt8188_scpsys_data = {
+       .domains_data = scpsys_domain_data_mt8188,
+       .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8188),
+};
+
+#endif /* __SOC_MEDIATEK_MT8188_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt8192-pm-domains.h b/drivers/pmdomain/mediatek/mt8192-pm-domains.h
new file mode 100644 (file)
index 0000000..b97b205
--- /dev/null
@@ -0,0 +1,355 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MT8192_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8192_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mt8192-power.h>
+
+/*
+ * MT8192 power domain support
+ */
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = {
+       [MT8192_POWER_DOMAIN_AUDIO] = {
+               .name = "audio",
+               .sta_mask = BIT(21),
+               .ctl_offs = 0x0354,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_AUDIO,
+                                   MT8192_TOP_AXI_PROT_EN_2_SET,
+                                   MT8192_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_2_STA1),
+               },
+       },
+       [MT8192_POWER_DOMAIN_CONN] = {
+               .name = "conn",
+               .sta_mask = PWR_STATUS_CONN,
+               .ctl_offs = 0x0304,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = 0,
+               .sram_pdn_ack_bits = 0,
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_CONN,
+                                   MT8192_TOP_AXI_PROT_EN_SET,
+                                   MT8192_TOP_AXI_PROT_EN_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_CONN_2ND,
+                                   MT8192_TOP_AXI_PROT_EN_SET,
+                                   MT8192_TOP_AXI_PROT_EN_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_1_CONN,
+                                   MT8192_TOP_AXI_PROT_EN_1_SET,
+                                   MT8192_TOP_AXI_PROT_EN_1_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_1_STA1),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8192_POWER_DOMAIN_MFG0] = {
+               .name = "mfg0",
+               .sta_mask = BIT(2),
+               .ctl_offs = 0x0308,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .caps = MTK_SCPD_DOMAIN_SUPPLY,
+       },
+       [MT8192_POWER_DOMAIN_MFG1] = {
+               .name = "mfg1",
+               .sta_mask = BIT(3),
+               .ctl_offs = 0x030c,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_1_MFG1,
+                                   MT8192_TOP_AXI_PROT_EN_1_SET,
+                                   MT8192_TOP_AXI_PROT_EN_1_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_1_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_MFG1,
+                                   MT8192_TOP_AXI_PROT_EN_2_SET,
+                                   MT8192_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_2_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MFG1,
+                                   MT8192_TOP_AXI_PROT_EN_SET,
+                                   MT8192_TOP_AXI_PROT_EN_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_MFG1_2ND,
+                                   MT8192_TOP_AXI_PROT_EN_2_SET,
+                                   MT8192_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_2_STA1),
+               },
+               .caps = MTK_SCPD_DOMAIN_SUPPLY,
+       },
+       [MT8192_POWER_DOMAIN_MFG2] = {
+               .name = "mfg2",
+               .sta_mask = BIT(4),
+               .ctl_offs = 0x0310,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+       },
+       [MT8192_POWER_DOMAIN_MFG3] = {
+               .name = "mfg3",
+               .sta_mask = BIT(5),
+               .ctl_offs = 0x0314,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+       },
+       [MT8192_POWER_DOMAIN_MFG4] = {
+               .name = "mfg4",
+               .sta_mask = BIT(6),
+               .ctl_offs = 0x0318,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+       },
+       [MT8192_POWER_DOMAIN_MFG5] = {
+               .name = "mfg5",
+               .sta_mask = BIT(7),
+               .ctl_offs = 0x031c,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+       },
+       [MT8192_POWER_DOMAIN_MFG6] = {
+               .name = "mfg6",
+               .sta_mask = BIT(8),
+               .ctl_offs = 0x0320,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+       },
+       [MT8192_POWER_DOMAIN_DISP] = {
+               .name = "disp",
+               .sta_mask = BIT(20),
+               .ctl_offs = 0x0350,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR_IGN(MT8192_TOP_AXI_PROT_EN_MM_DISP,
+                                       MT8192_TOP_AXI_PROT_EN_MM_SET,
+                                       MT8192_TOP_AXI_PROT_EN_MM_CLR,
+                                       MT8192_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR_IGN(MT8192_TOP_AXI_PROT_EN_MM_2_DISP,
+                                       MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+                                       MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+                                       MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_DISP,
+                                   MT8192_TOP_AXI_PROT_EN_SET,
+                                   MT8192_TOP_AXI_PROT_EN_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_DISP_2ND,
+                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_DISP_2ND,
+                                   MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+               },
+       },
+       [MT8192_POWER_DOMAIN_IPE] = {
+               .name = "ipe",
+               .sta_mask = BIT(14),
+               .ctl_offs = 0x0338,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_IPE,
+                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_IPE_2ND,
+                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
+               },
+       },
+       [MT8192_POWER_DOMAIN_ISP] = {
+               .name = "isp",
+               .sta_mask = BIT(12),
+               .ctl_offs = 0x0330,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_ISP,
+                                   MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_ISP_2ND,
+                                   MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+               },
+       },
+       [MT8192_POWER_DOMAIN_ISP2] = {
+               .name = "isp2",
+               .sta_mask = BIT(13),
+               .ctl_offs = 0x0334,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_ISP2,
+                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_ISP2_2ND,
+                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
+               },
+       },
+       [MT8192_POWER_DOMAIN_MDP] = {
+               .name = "mdp",
+               .sta_mask = BIT(19),
+               .ctl_offs = 0x034c,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_MDP,
+                                   MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_MDP_2ND,
+                                   MT8192_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
+               },
+       },
+       [MT8192_POWER_DOMAIN_VENC] = {
+               .name = "venc",
+               .sta_mask = BIT(17),
+               .ctl_offs = 0x0344,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VENC,
+                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VENC_2ND,
+                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
+               },
+       },
+       [MT8192_POWER_DOMAIN_VDEC] = {
+               .name = "vdec",
+               .sta_mask = BIT(15),
+               .ctl_offs = 0x033c,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VDEC,
+                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VDEC_2ND,
+                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
+               },
+       },
+       [MT8192_POWER_DOMAIN_VDEC2] = {
+               .name = "vdec2",
+               .sta_mask = BIT(16),
+               .ctl_offs = 0x0340,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+       },
+       [MT8192_POWER_DOMAIN_CAM] = {
+               .name = "cam",
+               .sta_mask = BIT(23),
+               .ctl_offs = 0x035c,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_CAM,
+                                   MT8192_TOP_AXI_PROT_EN_2_SET,
+                                   MT8192_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_2_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_CAM,
+                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_1_CAM,
+                                   MT8192_TOP_AXI_PROT_EN_1_SET,
+                                   MT8192_TOP_AXI_PROT_EN_1_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_1_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_CAM_2ND,
+                                   MT8192_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8192_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_VDNR_CAM,
+                                   MT8192_TOP_AXI_PROT_EN_VDNR_SET,
+                                   MT8192_TOP_AXI_PROT_EN_VDNR_CLR,
+                                   MT8192_TOP_AXI_PROT_EN_VDNR_STA1),
+               },
+       },
+       [MT8192_POWER_DOMAIN_CAM_RAWA] = {
+               .name = "cam_rawa",
+               .sta_mask = BIT(24),
+               .ctl_offs = 0x0360,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+       },
+       [MT8192_POWER_DOMAIN_CAM_RAWB] = {
+               .name = "cam_rawb",
+               .sta_mask = BIT(25),
+               .ctl_offs = 0x0364,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+       },
+       [MT8192_POWER_DOMAIN_CAM_RAWC] = {
+               .name = "cam_rawc",
+               .sta_mask = BIT(26),
+               .ctl_offs = 0x0368,
+               .pwr_sta_offs = 0x016c,
+               .pwr_sta2nd_offs = 0x0170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+       },
+};
+
+static const struct scpsys_soc_data mt8192_scpsys_data = {
+       .domains_data = scpsys_domain_data_mt8192,
+       .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8192),
+};
+
+#endif /* __SOC_MEDIATEK_MT8192_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mt8195-pm-domains.h b/drivers/pmdomain/mediatek/mt8195-pm-domains.h
new file mode 100644 (file)
index 0000000..d7387ea
--- /dev/null
@@ -0,0 +1,613 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Chun-Jie Chen <chun-jie.chen@mediatek.com>
+ */
+
+#ifndef __SOC_MEDIATEK_MT8195_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MT8195_PM_DOMAINS_H
+
+#include "mtk-pm-domains.h"
+#include <dt-bindings/power/mt8195-power.h>
+
+/*
+ * MT8195 power domain support
+ */
+
+static const struct scpsys_domain_data scpsys_domain_data_mt8195[] = {
+       [MT8195_POWER_DOMAIN_PCIE_MAC_P0] = {
+               .name = "pcie_mac_p0",
+               .sta_mask = BIT(11),
+               .ctl_offs = 0x328,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_PCIE_MAC_P0,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_SET,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_1_PCIE_MAC_P0,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_SET,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1),
+               },
+       },
+       [MT8195_POWER_DOMAIN_PCIE_MAC_P1] = {
+               .name = "pcie_mac_p1",
+               .sta_mask = BIT(12),
+               .ctl_offs = 0x32C,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_PCIE_MAC_P1,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_SET,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_1_PCIE_MAC_P1,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_SET,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1),
+               },
+       },
+       [MT8195_POWER_DOMAIN_PCIE_PHY] = {
+               .name = "pcie_phy",
+               .sta_mask = BIT(13),
+               .ctl_offs = 0x330,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT8195_POWER_DOMAIN_SSUSB_PCIE_PHY] = {
+               .name = "ssusb_pcie_phy",
+               .sta_mask = BIT(14),
+               .ctl_offs = 0x334,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .caps = MTK_SCPD_ACTIVE_WAKEUP | MTK_SCPD_ALWAYS_ON,
+       },
+       [MT8195_POWER_DOMAIN_CSI_RX_TOP] = {
+               .name = "csi_rx_top",
+               .sta_mask = BIT(18),
+               .ctl_offs = 0x3C4,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_ETHER] = {
+               .name = "ether",
+               .sta_mask = BIT(3),
+               .ctl_offs = 0x344,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT8195_POWER_DOMAIN_ADSP] = {
+               .name = "adsp",
+               .sta_mask = BIT(10),
+               .ctl_offs = 0x360,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_ADSP,
+                                   MT8195_TOP_AXI_PROT_EN_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_2_STA1),
+               },
+               .caps = MTK_SCPD_SRAM_ISO | MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT8195_POWER_DOMAIN_AUDIO] = {
+               .name = "audio",
+               .sta_mask = BIT(8),
+               .ctl_offs = 0x358,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_AUDIO,
+                                   MT8195_TOP_AXI_PROT_EN_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_2_STA1),
+               },
+       },
+       [MT8195_POWER_DOMAIN_MFG0] = {
+               .name = "mfg0",
+               .sta_mask = BIT(1),
+               .ctl_offs = 0x300,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
+       },
+       [MT8195_POWER_DOMAIN_MFG1] = {
+               .name = "mfg1",
+               .sta_mask = BIT(2),
+               .ctl_offs = 0x304,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MFG1,
+                                   MT8195_TOP_AXI_PROT_EN_SET,
+                                   MT8195_TOP_AXI_PROT_EN_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_MFG1,
+                                   MT8195_TOP_AXI_PROT_EN_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_2_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_1_MFG1,
+                                   MT8195_TOP_AXI_PROT_EN_1_SET,
+                                   MT8195_TOP_AXI_PROT_EN_1_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_1_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_MFG1_2ND,
+                                   MT8195_TOP_AXI_PROT_EN_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_2_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MFG1_2ND,
+                                   MT8195_TOP_AXI_PROT_EN_SET,
+                                   MT8195_TOP_AXI_PROT_EN_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_MFG1,
+                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_DOMAIN_SUPPLY,
+       },
+       [MT8195_POWER_DOMAIN_MFG2] = {
+               .name = "mfg2",
+               .sta_mask = BIT(3),
+               .ctl_offs = 0x308,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_MFG3] = {
+               .name = "mfg3",
+               .sta_mask = BIT(4),
+               .ctl_offs = 0x30C,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_MFG4] = {
+               .name = "mfg4",
+               .sta_mask = BIT(5),
+               .ctl_offs = 0x310,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_MFG5] = {
+               .name = "mfg5",
+               .sta_mask = BIT(6),
+               .ctl_offs = 0x314,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_MFG6] = {
+               .name = "mfg6",
+               .sta_mask = BIT(7),
+               .ctl_offs = 0x318,
+               .pwr_sta_offs = 0x174,
+               .pwr_sta2nd_offs = 0x178,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_VPPSYS0] = {
+               .name = "vppsys0",
+               .sta_mask = BIT(11),
+               .ctl_offs = 0x364,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VPPSYS0,
+                                   MT8195_TOP_AXI_PROT_EN_SET,
+                                   MT8195_TOP_AXI_PROT_EN_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS0,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VPPSYS0_2ND,
+                                   MT8195_TOP_AXI_PROT_EN_SET,
+                                   MT8195_TOP_AXI_PROT_EN_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS0_2ND,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VPPSYS0,
+                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1),
+               },
+       },
+       [MT8195_POWER_DOMAIN_VDOSYS0] = {
+               .name = "vdosys0",
+               .sta_mask = BIT(13),
+               .ctl_offs = 0x36C,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDOSYS0,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDOSYS0,
+                                   MT8195_TOP_AXI_PROT_EN_SET,
+                                   MT8195_TOP_AXI_PROT_EN_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_VDOSYS0,
+                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_SET,
+                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_SUB_INFRA_VDNR_STA1),
+               },
+       },
+       [MT8195_POWER_DOMAIN_VPPSYS1] = {
+               .name = "vppsys1",
+               .sta_mask = BIT(12),
+               .ctl_offs = 0x368,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VPPSYS1,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VPPSYS1_2ND,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VPPSYS1,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+               },
+       },
+       [MT8195_POWER_DOMAIN_VDOSYS1] = {
+               .name = "vdosys1",
+               .sta_mask = BIT(14),
+               .ctl_offs = 0x370,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDOSYS1,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDOSYS1_2ND,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDOSYS1,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+               },
+       },
+       [MT8195_POWER_DOMAIN_DP_TX] = {
+               .name = "dp_tx",
+               .sta_mask = BIT(16),
+               .ctl_offs = 0x378,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_1_DP_TX,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_SET,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_EPD_TX] = {
+               .name = "epd_tx",
+               .sta_mask = BIT(17),
+               .ctl_offs = 0x37C,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_VDNR_1_EPD_TX,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_SET,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_VDNR_1_STA1),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_HDMI_TX] = {
+               .name = "hdmi_tx",
+               .sta_mask = BIT(18),
+               .ctl_offs = 0x380,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF | MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT8195_POWER_DOMAIN_WPESYS] = {
+               .name = "wpesys",
+               .sta_mask = BIT(15),
+               .ctl_offs = 0x374,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_WPESYS,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_WPESYS,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_WPESYS_2ND,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+               },
+       },
+       [MT8195_POWER_DOMAIN_VDEC0] = {
+               .name = "vdec0",
+               .sta_mask = BIT(20),
+               .ctl_offs = 0x388,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDEC0,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDEC0,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDEC0_2ND,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDEC0_2ND,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_VDEC1] = {
+               .name = "vdec1",
+               .sta_mask = BIT(21),
+               .ctl_offs = 0x38C,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDEC1,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VDEC1_2ND,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_VDEC2] = {
+               .name = "vdec2",
+               .sta_mask = BIT(22),
+               .ctl_offs = 0x390,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDEC2,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VDEC2_2ND,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_VENC] = {
+               .name = "venc",
+               .sta_mask = BIT(23),
+               .ctl_offs = 0x394,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VENC,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VENC_2ND,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VENC,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_VENC_CORE1] = {
+               .name = "venc_core1",
+               .sta_mask = BIT(24),
+               .ctl_offs = 0x398,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_VENC_CORE1,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_VENC_CORE1,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_IMG] = {
+               .name = "img",
+               .sta_mask = BIT(29),
+               .ctl_offs = 0x3AC,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_IMG,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_IMG_2ND,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_DIP] = {
+               .name = "dip",
+               .sta_mask = BIT(30),
+               .ctl_offs = 0x3B0,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_IPE] = {
+               .name = "ipe",
+               .sta_mask = BIT(31),
+               .ctl_offs = 0x3B4,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_IPE,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_IPE,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_CAM] = {
+               .name = "cam",
+               .sta_mask = BIT(25),
+               .ctl_offs = 0x39C,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .bp_infracfg = {
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_2_CAM,
+                                   MT8195_TOP_AXI_PROT_EN_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_2_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_CAM,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_1_CAM,
+                                   MT8195_TOP_AXI_PROT_EN_1_SET,
+                                   MT8195_TOP_AXI_PROT_EN_1_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_1_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_CAM_2ND,
+                                   MT8195_TOP_AXI_PROT_EN_MM_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_STA1),
+                       BUS_PROT_WR(MT8195_TOP_AXI_PROT_EN_MM_2_CAM,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_SET,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_CLR,
+                                   MT8195_TOP_AXI_PROT_EN_MM_2_STA1),
+               },
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_CAM_RAWA] = {
+               .name = "cam_rawa",
+               .sta_mask = BIT(26),
+               .ctl_offs = 0x3A0,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_CAM_RAWB] = {
+               .name = "cam_rawb",
+               .sta_mask = BIT(27),
+               .ctl_offs = 0x3A4,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+       [MT8195_POWER_DOMAIN_CAM_MRAW] = {
+               .name = "cam_mraw",
+               .sta_mask = BIT(28),
+               .ctl_offs = 0x3A8,
+               .pwr_sta_offs = 0x16c,
+               .pwr_sta2nd_offs = 0x170,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .caps = MTK_SCPD_KEEP_DEFAULT_OFF,
+       },
+};
+
+static const struct scpsys_soc_data mt8195_scpsys_data = {
+       .domains_data = scpsys_domain_data_mt8195,
+       .num_domains = ARRAY_SIZE(scpsys_domain_data_mt8195),
+};
+
+#endif /* __SOC_MEDIATEK_MT8195_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
new file mode 100644 (file)
index 0000000..ee96280
--- /dev/null
@@ -0,0 +1,688 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020 Collabora Ltd.
+ */
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_clk.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/soc/mediatek/infracfg.h>
+
+#include "mt6795-pm-domains.h"
+#include "mt8167-pm-domains.h"
+#include "mt8173-pm-domains.h"
+#include "mt8183-pm-domains.h"
+#include "mt8186-pm-domains.h"
+#include "mt8188-pm-domains.h"
+#include "mt8192-pm-domains.h"
+#include "mt8195-pm-domains.h"
+
+#define MTK_POLL_DELAY_US              10
+#define MTK_POLL_TIMEOUT               USEC_PER_SEC
+
+#define PWR_RST_B_BIT                  BIT(0)
+#define PWR_ISO_BIT                    BIT(1)
+#define PWR_ON_BIT                     BIT(2)
+#define PWR_ON_2ND_BIT                 BIT(3)
+#define PWR_CLK_DIS_BIT                        BIT(4)
+#define PWR_SRAM_CLKISO_BIT            BIT(5)
+#define PWR_SRAM_ISOINT_B_BIT          BIT(6)
+
+struct scpsys_domain {
+       struct generic_pm_domain genpd;
+       const struct scpsys_domain_data *data;
+       struct scpsys *scpsys;
+       int num_clks;
+       struct clk_bulk_data *clks;
+       int num_subsys_clks;
+       struct clk_bulk_data *subsys_clks;
+       struct regmap *infracfg;
+       struct regmap *smi;
+       struct regulator *supply;
+};
+
+struct scpsys {
+       struct device *dev;
+       struct regmap *base;
+       const struct scpsys_soc_data *soc_data;
+       struct genpd_onecell_data pd_data;
+       struct generic_pm_domain *domains[];
+};
+
+#define to_scpsys_domain(gpd) container_of(gpd, struct scpsys_domain, genpd)
+
+static bool scpsys_domain_is_on(struct scpsys_domain *pd)
+{
+       struct scpsys *scpsys = pd->scpsys;
+       u32 status, status2;
+
+       regmap_read(scpsys->base, pd->data->pwr_sta_offs, &status);
+       status &= pd->data->sta_mask;
+
+       regmap_read(scpsys->base, pd->data->pwr_sta2nd_offs, &status2);
+       status2 &= pd->data->sta_mask;
+
+       /* A domain is on when both status bits are set. */
+       return status && status2;
+}
+
+static int scpsys_sram_enable(struct scpsys_domain *pd)
+{
+       u32 pdn_ack = pd->data->sram_pdn_ack_bits;
+       struct scpsys *scpsys = pd->scpsys;
+       unsigned int tmp;
+       int ret;
+
+       regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
+
+       /* Either wait until SRAM_PDN_ACK all 1 or 0 */
+       ret = regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
+                                      (tmp & pdn_ack) == 0, MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+       if (ret < 0)
+               return ret;
+
+       if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_ISO)) {
+               regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
+               udelay(1);
+               regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT);
+       }
+
+       return 0;
+}
+
+static int scpsys_sram_disable(struct scpsys_domain *pd)
+{
+       u32 pdn_ack = pd->data->sram_pdn_ack_bits;
+       struct scpsys *scpsys = pd->scpsys;
+       unsigned int tmp;
+
+       if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_ISO)) {
+               regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT);
+               udelay(1);
+               regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
+       }
+
+       regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
+
+       /* Either wait until SRAM_PDN_ACK all 1 or 0 */
+       return regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
+                                       (tmp & pdn_ack) == pdn_ack, MTK_POLL_DELAY_US,
+                                       MTK_POLL_TIMEOUT);
+}
+
+static int _scpsys_bus_protect_enable(const struct scpsys_bus_prot_data *bpd, struct regmap *regmap)
+{
+       int i, ret;
+
+       for (i = 0; i < SPM_MAX_BUS_PROT_DATA; i++) {
+               u32 val, mask = bpd[i].bus_prot_mask;
+
+               if (!mask)
+                       break;
+
+               if (bpd[i].bus_prot_reg_update)
+                       regmap_set_bits(regmap, bpd[i].bus_prot_set, mask);
+               else
+                       regmap_write(regmap, bpd[i].bus_prot_set, mask);
+
+               ret = regmap_read_poll_timeout(regmap, bpd[i].bus_prot_sta,
+                                              val, (val & mask) == mask,
+                                              MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int scpsys_bus_protect_enable(struct scpsys_domain *pd)
+{
+       int ret;
+
+       ret = _scpsys_bus_protect_enable(pd->data->bp_infracfg, pd->infracfg);
+       if (ret)
+               return ret;
+
+       return _scpsys_bus_protect_enable(pd->data->bp_smi, pd->smi);
+}
+
+static int _scpsys_bus_protect_disable(const struct scpsys_bus_prot_data *bpd,
+                                      struct regmap *regmap)
+{
+       int i, ret;
+
+       for (i = SPM_MAX_BUS_PROT_DATA - 1; i >= 0; i--) {
+               u32 val, mask = bpd[i].bus_prot_mask;
+
+               if (!mask)
+                       continue;
+
+               if (bpd[i].bus_prot_reg_update)
+                       regmap_clear_bits(regmap, bpd[i].bus_prot_clr, mask);
+               else
+                       regmap_write(regmap, bpd[i].bus_prot_clr, mask);
+
+               if (bpd[i].ignore_clr_ack)
+                       continue;
+
+               ret = regmap_read_poll_timeout(regmap, bpd[i].bus_prot_sta,
+                                              val, !(val & mask),
+                                              MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int scpsys_bus_protect_disable(struct scpsys_domain *pd)
+{
+       int ret;
+
+       ret = _scpsys_bus_protect_disable(pd->data->bp_smi, pd->smi);
+       if (ret)
+               return ret;
+
+       return _scpsys_bus_protect_disable(pd->data->bp_infracfg, pd->infracfg);
+}
+
+static int scpsys_regulator_enable(struct regulator *supply)
+{
+       return supply ? regulator_enable(supply) : 0;
+}
+
+static int scpsys_regulator_disable(struct regulator *supply)
+{
+       return supply ? regulator_disable(supply) : 0;
+}
+
+static int scpsys_power_on(struct generic_pm_domain *genpd)
+{
+       struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
+       struct scpsys *scpsys = pd->scpsys;
+       bool tmp;
+       int ret;
+
+       ret = scpsys_regulator_enable(pd->supply);
+       if (ret)
+               return ret;
+
+       ret = clk_bulk_prepare_enable(pd->num_clks, pd->clks);
+       if (ret)
+               goto err_reg;
+
+       if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO))
+               regmap_clear_bits(scpsys->base, pd->data->ext_buck_iso_offs,
+                                 pd->data->ext_buck_iso_mask);
+
+       /* subsys power on */
+       regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
+       regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
+
+       /* wait until PWR_ACK = 1 */
+       ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, tmp, MTK_POLL_DELAY_US,
+                                MTK_POLL_TIMEOUT);
+       if (ret < 0)
+               goto err_pwr_ack;
+
+       regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
+       regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
+       regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
+
+       ret = clk_bulk_prepare_enable(pd->num_subsys_clks, pd->subsys_clks);
+       if (ret)
+               goto err_pwr_ack;
+
+       ret = scpsys_sram_enable(pd);
+       if (ret < 0)
+               goto err_disable_subsys_clks;
+
+       ret = scpsys_bus_protect_disable(pd);
+       if (ret < 0)
+               goto err_disable_sram;
+
+       return 0;
+
+err_disable_sram:
+       scpsys_sram_disable(pd);
+err_disable_subsys_clks:
+       clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks);
+err_pwr_ack:
+       clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
+err_reg:
+       scpsys_regulator_disable(pd->supply);
+       return ret;
+}
+
+static int scpsys_power_off(struct generic_pm_domain *genpd)
+{
+       struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
+       struct scpsys *scpsys = pd->scpsys;
+       bool tmp;
+       int ret;
+
+       ret = scpsys_bus_protect_enable(pd);
+       if (ret < 0)
+               return ret;
+
+       ret = scpsys_sram_disable(pd);
+       if (ret < 0)
+               return ret;
+
+       if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO))
+               regmap_set_bits(scpsys->base, pd->data->ext_buck_iso_offs,
+                               pd->data->ext_buck_iso_mask);
+
+       clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks);
+
+       /* subsys power off */
+       regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
+       regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
+       regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
+       regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
+       regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
+
+       /* wait until PWR_ACK = 0 */
+       ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, !tmp, MTK_POLL_DELAY_US,
+                                MTK_POLL_TIMEOUT);
+       if (ret < 0)
+               return ret;
+
+       clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
+
+       scpsys_regulator_disable(pd->supply);
+
+       return 0;
+}
+
+static struct
+generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_node *node)
+{
+       const struct scpsys_domain_data *domain_data;
+       struct scpsys_domain *pd;
+       struct device_node *root_node = scpsys->dev->of_node;
+       struct device_node *smi_node;
+       struct property *prop;
+       const char *clk_name;
+       int i, ret, num_clks;
+       struct clk *clk;
+       int clk_ind = 0;
+       u32 id;
+
+       ret = of_property_read_u32(node, "reg", &id);
+       if (ret) {
+               dev_err(scpsys->dev, "%pOF: failed to retrieve domain id from reg: %d\n",
+                       node, ret);
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (id >= scpsys->soc_data->num_domains) {
+               dev_err(scpsys->dev, "%pOF: invalid domain id %d\n", node, id);
+               return ERR_PTR(-EINVAL);
+       }
+
+       domain_data = &scpsys->soc_data->domains_data[id];
+       if (domain_data->sta_mask == 0) {
+               dev_err(scpsys->dev, "%pOF: undefined domain id %d\n", node, id);
+               return ERR_PTR(-EINVAL);
+       }
+
+       pd = devm_kzalloc(scpsys->dev, sizeof(*pd), GFP_KERNEL);
+       if (!pd)
+               return ERR_PTR(-ENOMEM);
+
+       pd->data = domain_data;
+       pd->scpsys = scpsys;
+
+       if (MTK_SCPD_CAPS(pd, MTK_SCPD_DOMAIN_SUPPLY)) {
+               /*
+                * Find regulator in current power domain node.
+                * devm_regulator_get() finds regulator in a node and its child
+                * node, so set of_node to current power domain node then change
+                * back to original node after regulator is found for current
+                * power domain node.
+                */
+               scpsys->dev->of_node = node;
+               pd->supply = devm_regulator_get(scpsys->dev, "domain");
+               scpsys->dev->of_node = root_node;
+               if (IS_ERR(pd->supply)) {
+                       dev_err_probe(scpsys->dev, PTR_ERR(pd->supply),
+                                     "%pOF: failed to get power supply.\n",
+                                     node);
+                       return ERR_CAST(pd->supply);
+               }
+       }
+
+       pd->infracfg = syscon_regmap_lookup_by_phandle_optional(node, "mediatek,infracfg");
+       if (IS_ERR(pd->infracfg))
+               return ERR_CAST(pd->infracfg);
+
+       smi_node = of_parse_phandle(node, "mediatek,smi", 0);
+       if (smi_node) {
+               pd->smi = device_node_to_regmap(smi_node);
+               of_node_put(smi_node);
+               if (IS_ERR(pd->smi))
+                       return ERR_CAST(pd->smi);
+       }
+
+       num_clks = of_clk_get_parent_count(node);
+       if (num_clks > 0) {
+               /* Calculate number of subsys_clks */
+               of_property_for_each_string(node, "clock-names", prop, clk_name) {
+                       char *subsys;
+
+                       subsys = strchr(clk_name, '-');
+                       if (subsys)
+                               pd->num_subsys_clks++;
+                       else
+                               pd->num_clks++;
+               }
+
+               pd->clks = devm_kcalloc(scpsys->dev, pd->num_clks, sizeof(*pd->clks), GFP_KERNEL);
+               if (!pd->clks)
+                       return ERR_PTR(-ENOMEM);
+
+               pd->subsys_clks = devm_kcalloc(scpsys->dev, pd->num_subsys_clks,
+                                              sizeof(*pd->subsys_clks), GFP_KERNEL);
+               if (!pd->subsys_clks)
+                       return ERR_PTR(-ENOMEM);
+
+       }
+
+       for (i = 0; i < pd->num_clks; i++) {
+               clk = of_clk_get(node, i);
+               if (IS_ERR(clk)) {
+                       ret = PTR_ERR(clk);
+                       dev_err_probe(scpsys->dev, ret,
+                                     "%pOF: failed to get clk at index %d\n", node, i);
+                       goto err_put_clocks;
+               }
+
+               pd->clks[clk_ind++].clk = clk;
+       }
+
+       for (i = 0; i < pd->num_subsys_clks; i++) {
+               clk = of_clk_get(node, i + clk_ind);
+               if (IS_ERR(clk)) {
+                       ret = PTR_ERR(clk);
+                       dev_err_probe(scpsys->dev, ret,
+                                     "%pOF: failed to get clk at index %d\n", node,
+                                     i + clk_ind);
+                       goto err_put_subsys_clocks;
+               }
+
+               pd->subsys_clks[i].clk = clk;
+       }
+
+       /*
+        * Initially turn on all domains to make the domains usable
+        * with !CONFIG_PM and to get the hardware in sync with the
+        * software.  The unused domains will be switched off during
+        * late_init time.
+        */
+       if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF)) {
+               if (scpsys_domain_is_on(pd))
+                       dev_warn(scpsys->dev,
+                                "%pOF: A default off power domain has been ON\n", node);
+       } else {
+               ret = scpsys_power_on(&pd->genpd);
+               if (ret < 0) {
+                       dev_err(scpsys->dev, "%pOF: failed to power on domain: %d\n", node, ret);
+                       goto err_put_subsys_clocks;
+               }
+
+               if (MTK_SCPD_CAPS(pd, MTK_SCPD_ALWAYS_ON))
+                       pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
+       }
+
+       if (scpsys->domains[id]) {
+               ret = -EINVAL;
+               dev_err(scpsys->dev,
+                       "power domain with id %d already exists, check your device-tree\n", id);
+               goto err_put_subsys_clocks;
+       }
+
+       if (!pd->data->name)
+               pd->genpd.name = node->name;
+       else
+               pd->genpd.name = pd->data->name;
+
+       pd->genpd.power_off = scpsys_power_off;
+       pd->genpd.power_on = scpsys_power_on;
+
+       if (MTK_SCPD_CAPS(pd, MTK_SCPD_ACTIVE_WAKEUP))
+               pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
+
+       if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF))
+               pm_genpd_init(&pd->genpd, NULL, true);
+       else
+               pm_genpd_init(&pd->genpd, NULL, false);
+
+       scpsys->domains[id] = &pd->genpd;
+
+       return scpsys->pd_data.domains[id];
+
+err_put_subsys_clocks:
+       clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
+err_put_clocks:
+       clk_bulk_put(pd->num_clks, pd->clks);
+       return ERR_PTR(ret);
+}
+
+static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *parent)
+{
+       struct generic_pm_domain *child_pd, *parent_pd;
+       struct device_node *child;
+       int ret;
+
+       for_each_child_of_node(parent, child) {
+               u32 id;
+
+               ret = of_property_read_u32(parent, "reg", &id);
+               if (ret) {
+                       dev_err(scpsys->dev, "%pOF: failed to get parent domain id\n", child);
+                       goto err_put_node;
+               }
+
+               if (!scpsys->pd_data.domains[id]) {
+                       ret = -EINVAL;
+                       dev_err(scpsys->dev, "power domain with id %d does not exist\n", id);
+                       goto err_put_node;
+               }
+
+               parent_pd = scpsys->pd_data.domains[id];
+
+               child_pd = scpsys_add_one_domain(scpsys, child);
+               if (IS_ERR(child_pd)) {
+                       ret = PTR_ERR(child_pd);
+                       dev_err_probe(scpsys->dev, ret, "%pOF: failed to get child domain id\n",
+                                     child);
+                       goto err_put_node;
+               }
+
+               ret = pm_genpd_add_subdomain(parent_pd, child_pd);
+               if (ret) {
+                       dev_err(scpsys->dev, "failed to add %s subdomain to parent %s\n",
+                               child_pd->name, parent_pd->name);
+                       goto err_put_node;
+               } else {
+                       dev_dbg(scpsys->dev, "%s add subdomain: %s\n", parent_pd->name,
+                               child_pd->name);
+               }
+
+               /* recursive call to add all subdomains */
+               ret = scpsys_add_subdomain(scpsys, child);
+               if (ret)
+                       goto err_put_node;
+       }
+
+       return 0;
+
+err_put_node:
+       of_node_put(child);
+       return ret;
+}
+
+static void scpsys_remove_one_domain(struct scpsys_domain *pd)
+{
+       int ret;
+
+       if (scpsys_domain_is_on(pd))
+               scpsys_power_off(&pd->genpd);
+
+       /*
+        * We're in the error cleanup already, so we only complain,
+        * but won't emit another error on top of the original one.
+        */
+       ret = pm_genpd_remove(&pd->genpd);
+       if (ret < 0)
+               dev_err(pd->scpsys->dev,
+                       "failed to remove domain '%s' : %d - state may be inconsistent\n",
+                       pd->genpd.name, ret);
+
+       clk_bulk_put(pd->num_clks, pd->clks);
+       clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
+}
+
+static void scpsys_domain_cleanup(struct scpsys *scpsys)
+{
+       struct generic_pm_domain *genpd;
+       struct scpsys_domain *pd;
+       int i;
+
+       for (i = scpsys->pd_data.num_domains - 1; i >= 0; i--) {
+               genpd = scpsys->pd_data.domains[i];
+               if (genpd) {
+                       pd = to_scpsys_domain(genpd);
+                       scpsys_remove_one_domain(pd);
+               }
+       }
+}
+
+static const struct of_device_id scpsys_of_match[] = {
+       {
+               .compatible = "mediatek,mt6795-power-controller",
+               .data = &mt6795_scpsys_data,
+       },
+       {
+               .compatible = "mediatek,mt8167-power-controller",
+               .data = &mt8167_scpsys_data,
+       },
+       {
+               .compatible = "mediatek,mt8173-power-controller",
+               .data = &mt8173_scpsys_data,
+       },
+       {
+               .compatible = "mediatek,mt8183-power-controller",
+               .data = &mt8183_scpsys_data,
+       },
+       {
+               .compatible = "mediatek,mt8186-power-controller",
+               .data = &mt8186_scpsys_data,
+       },
+       {
+               .compatible = "mediatek,mt8188-power-controller",
+               .data = &mt8188_scpsys_data,
+       },
+       {
+               .compatible = "mediatek,mt8192-power-controller",
+               .data = &mt8192_scpsys_data,
+       },
+       {
+               .compatible = "mediatek,mt8195-power-controller",
+               .data = &mt8195_scpsys_data,
+       },
+       { }
+};
+
+static int scpsys_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       const struct scpsys_soc_data *soc;
+       struct device_node *node;
+       struct device *parent;
+       struct scpsys *scpsys;
+       int ret;
+
+       soc = of_device_get_match_data(&pdev->dev);
+       if (!soc) {
+               dev_err(&pdev->dev, "no power controller data\n");
+               return -EINVAL;
+       }
+
+       scpsys = devm_kzalloc(dev, struct_size(scpsys, domains, soc->num_domains), GFP_KERNEL);
+       if (!scpsys)
+               return -ENOMEM;
+
+       scpsys->dev = dev;
+       scpsys->soc_data = soc;
+
+       scpsys->pd_data.domains = scpsys->domains;
+       scpsys->pd_data.num_domains = soc->num_domains;
+
+       parent = dev->parent;
+       if (!parent) {
+               dev_err(dev, "no parent for syscon devices\n");
+               return -ENODEV;
+       }
+
+       scpsys->base = syscon_node_to_regmap(parent->of_node);
+       if (IS_ERR(scpsys->base)) {
+               dev_err(dev, "no regmap available\n");
+               return PTR_ERR(scpsys->base);
+       }
+
+       ret = -ENODEV;
+       for_each_available_child_of_node(np, node) {
+               struct generic_pm_domain *domain;
+
+               domain = scpsys_add_one_domain(scpsys, node);
+               if (IS_ERR(domain)) {
+                       ret = PTR_ERR(domain);
+                       of_node_put(node);
+                       goto err_cleanup_domains;
+               }
+
+               ret = scpsys_add_subdomain(scpsys, node);
+               if (ret) {
+                       of_node_put(node);
+                       goto err_cleanup_domains;
+               }
+       }
+
+       if (ret) {
+               dev_dbg(dev, "no power domains present\n");
+               return ret;
+       }
+
+       ret = of_genpd_add_provider_onecell(np, &scpsys->pd_data);
+       if (ret) {
+               dev_err(dev, "failed to add provider: %d\n", ret);
+               goto err_cleanup_domains;
+       }
+
+       return 0;
+
+err_cleanup_domains:
+       scpsys_domain_cleanup(scpsys);
+       return ret;
+}
+
+static struct platform_driver scpsys_pm_domain_driver = {
+       .probe = scpsys_probe,
+       .driver = {
+               .name = "mtk-power-controller",
+               .suppress_bind_attrs = true,
+               .of_match_table = scpsys_of_match,
+       },
+};
+builtin_platform_driver(scpsys_pm_domain_driver);
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.h b/drivers/pmdomain/mediatek/mtk-pm-domains.h
new file mode 100644 (file)
index 0000000..5ec53ee
--- /dev/null
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MTK_PM_DOMAINS_H
+#define __SOC_MEDIATEK_MTK_PM_DOMAINS_H
+
+#define MTK_SCPD_ACTIVE_WAKEUP         BIT(0)
+#define MTK_SCPD_FWAIT_SRAM            BIT(1)
+#define MTK_SCPD_SRAM_ISO              BIT(2)
+#define MTK_SCPD_KEEP_DEFAULT_OFF      BIT(3)
+#define MTK_SCPD_DOMAIN_SUPPLY         BIT(4)
+/* can't set MTK_SCPD_KEEP_DEFAULT_OFF at the same time */
+#define MTK_SCPD_ALWAYS_ON             BIT(5)
+#define MTK_SCPD_EXT_BUCK_ISO          BIT(6)
+#define MTK_SCPD_CAPS(_scpd, _x)       ((_scpd)->data->caps & (_x))
+
+#define SPM_VDE_PWR_CON                        0x0210
+#define SPM_MFG_PWR_CON                        0x0214
+#define SPM_VEN_PWR_CON                        0x0230
+#define SPM_ISP_PWR_CON                        0x0238
+#define SPM_DIS_PWR_CON                        0x023c
+#define SPM_CONN_PWR_CON               0x0280
+#define SPM_VEN2_PWR_CON               0x0298
+#define SPM_AUDIO_PWR_CON              0x029c
+#define SPM_MFG_2D_PWR_CON             0x02c0
+#define SPM_MFG_ASYNC_PWR_CON          0x02c4
+#define SPM_USB_PWR_CON                        0x02cc
+
+#define SPM_PWR_STATUS                 0x060c
+#define SPM_PWR_STATUS_2ND             0x0610
+
+#define PWR_STATUS_CONN                        BIT(1)
+#define PWR_STATUS_DISP                        BIT(3)
+#define PWR_STATUS_MFG                 BIT(4)
+#define PWR_STATUS_ISP                 BIT(5)
+#define PWR_STATUS_VDEC                        BIT(7)
+#define PWR_STATUS_VENC_LT             BIT(20)
+#define PWR_STATUS_VENC                        BIT(21)
+#define PWR_STATUS_MFG_2D              BIT(22)
+#define PWR_STATUS_MFG_ASYNC           BIT(23)
+#define PWR_STATUS_AUDIO               BIT(24)
+#define PWR_STATUS_USB                 BIT(25)
+
+#define SPM_MAX_BUS_PROT_DATA          6
+
+#define _BUS_PROT(_mask, _set, _clr, _sta, _update, _ignore) { \
+               .bus_prot_mask = (_mask),                       \
+               .bus_prot_set = _set,                           \
+               .bus_prot_clr = _clr,                           \
+               .bus_prot_sta = _sta,                           \
+               .bus_prot_reg_update = _update,                 \
+               .ignore_clr_ack = _ignore,                      \
+       }
+
+#define BUS_PROT_WR(_mask, _set, _clr, _sta)                   \
+               _BUS_PROT(_mask, _set, _clr, _sta, false, false)
+
+#define BUS_PROT_WR_IGN(_mask, _set, _clr, _sta)               \
+               _BUS_PROT(_mask, _set, _clr, _sta, false, true)
+
+#define BUS_PROT_UPDATE(_mask, _set, _clr, _sta)               \
+               _BUS_PROT(_mask, _set, _clr, _sta, true, false)
+
+#define BUS_PROT_UPDATE_TOPAXI(_mask)                          \
+               BUS_PROT_UPDATE(_mask,                          \
+                               INFRA_TOPAXI_PROTECTEN,         \
+                               INFRA_TOPAXI_PROTECTEN,         \
+                               INFRA_TOPAXI_PROTECTSTA1)
+
+struct scpsys_bus_prot_data {
+       u32 bus_prot_mask;
+       u32 bus_prot_set;
+       u32 bus_prot_clr;
+       u32 bus_prot_sta;
+       bool bus_prot_reg_update;
+       bool ignore_clr_ack;
+};
+
+/**
+ * struct scpsys_domain_data - scp domain data for power on/off flow
+ * @name: The name of the power domain.
+ * @sta_mask: The mask for power on/off status bit.
+ * @ctl_offs: The offset for main power control register.
+ * @sram_pdn_bits: The mask for sram power control bits.
+ * @sram_pdn_ack_bits: The mask for sram power control acked bits.
+ * @ext_buck_iso_offs: The offset for external buck isolation
+ * @ext_buck_iso_mask: The mask for external buck isolation
+ * @caps: The flag for active wake-up action.
+ * @bp_infracfg: bus protection for infracfg subsystem
+ * @bp_smi: bus protection for smi subsystem
+ */
+struct scpsys_domain_data {
+       const char *name;
+       u32 sta_mask;
+       int ctl_offs;
+       u32 sram_pdn_bits;
+       u32 sram_pdn_ack_bits;
+       int ext_buck_iso_offs;
+       u32 ext_buck_iso_mask;
+       u8 caps;
+       const struct scpsys_bus_prot_data bp_infracfg[SPM_MAX_BUS_PROT_DATA];
+       const struct scpsys_bus_prot_data bp_smi[SPM_MAX_BUS_PROT_DATA];
+       int pwr_sta_offs;
+       int pwr_sta2nd_offs;
+};
+
+struct scpsys_soc_data {
+       const struct scpsys_domain_data *domains_data;
+       int num_domains;
+};
+
+#endif /* __SOC_MEDIATEK_MTK_PM_DOMAINS_H */
diff --git a/drivers/pmdomain/mediatek/mtk-scpsys.c b/drivers/pmdomain/mediatek/mtk-scpsys.c
new file mode 100644 (file)
index 0000000..b374d01
--- /dev/null
@@ -0,0 +1,1147 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
+ */
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/regulator/consumer.h>
+#include <linux/soc/mediatek/infracfg.h>
+
+#include <dt-bindings/power/mt2701-power.h>
+#include <dt-bindings/power/mt2712-power.h>
+#include <dt-bindings/power/mt6797-power.h>
+#include <dt-bindings/power/mt7622-power.h>
+#include <dt-bindings/power/mt7623a-power.h>
+#include <dt-bindings/power/mt8173-power.h>
+
+#define MTK_POLL_DELAY_US   10
+#define MTK_POLL_TIMEOUT    USEC_PER_SEC
+
+#define MTK_SCPD_ACTIVE_WAKEUP         BIT(0)
+#define MTK_SCPD_FWAIT_SRAM            BIT(1)
+#define MTK_SCPD_CAPS(_scpd, _x)       ((_scpd)->data->caps & (_x))
+
+#define SPM_VDE_PWR_CON                        0x0210
+#define SPM_MFG_PWR_CON                        0x0214
+#define SPM_VEN_PWR_CON                        0x0230
+#define SPM_ISP_PWR_CON                        0x0238
+#define SPM_DIS_PWR_CON                        0x023c
+#define SPM_CONN_PWR_CON               0x0280
+#define SPM_VEN2_PWR_CON               0x0298
+#define SPM_AUDIO_PWR_CON              0x029c  /* MT8173, MT2712 */
+#define SPM_BDP_PWR_CON                        0x029c  /* MT2701 */
+#define SPM_ETH_PWR_CON                        0x02a0
+#define SPM_HIF_PWR_CON                        0x02a4
+#define SPM_IFR_MSC_PWR_CON            0x02a8
+#define SPM_MFG_2D_PWR_CON             0x02c0
+#define SPM_MFG_ASYNC_PWR_CON          0x02c4
+#define SPM_USB_PWR_CON                        0x02cc
+#define SPM_USB2_PWR_CON               0x02d4  /* MT2712 */
+#define SPM_ETHSYS_PWR_CON             0x02e0  /* MT7622 */
+#define SPM_HIF0_PWR_CON               0x02e4  /* MT7622 */
+#define SPM_HIF1_PWR_CON               0x02e8  /* MT7622 */
+#define SPM_WB_PWR_CON                 0x02ec  /* MT7622 */
+
+#define SPM_PWR_STATUS                 0x060c
+#define SPM_PWR_STATUS_2ND             0x0610
+
+#define PWR_RST_B_BIT                  BIT(0)
+#define PWR_ISO_BIT                    BIT(1)
+#define PWR_ON_BIT                     BIT(2)
+#define PWR_ON_2ND_BIT                 BIT(3)
+#define PWR_CLK_DIS_BIT                        BIT(4)
+
+#define PWR_STATUS_CONN                        BIT(1)
+#define PWR_STATUS_DISP                        BIT(3)
+#define PWR_STATUS_MFG                 BIT(4)
+#define PWR_STATUS_ISP                 BIT(5)
+#define PWR_STATUS_VDEC                        BIT(7)
+#define PWR_STATUS_BDP                 BIT(14)
+#define PWR_STATUS_ETH                 BIT(15)
+#define PWR_STATUS_HIF                 BIT(16)
+#define PWR_STATUS_IFR_MSC             BIT(17)
+#define PWR_STATUS_USB2                        BIT(19) /* MT2712 */
+#define PWR_STATUS_VENC_LT             BIT(20)
+#define PWR_STATUS_VENC                        BIT(21)
+#define PWR_STATUS_MFG_2D              BIT(22) /* MT8173 */
+#define PWR_STATUS_MFG_ASYNC           BIT(23) /* MT8173 */
+#define PWR_STATUS_AUDIO               BIT(24) /* MT8173, MT2712 */
+#define PWR_STATUS_USB                 BIT(25) /* MT8173, MT2712 */
+#define PWR_STATUS_ETHSYS              BIT(24) /* MT7622 */
+#define PWR_STATUS_HIF0                        BIT(25) /* MT7622 */
+#define PWR_STATUS_HIF1                        BIT(26) /* MT7622 */
+#define PWR_STATUS_WB                  BIT(27) /* MT7622 */
+
+enum clk_id {
+       CLK_NONE,
+       CLK_MM,
+       CLK_MFG,
+       CLK_VENC,
+       CLK_VENC_LT,
+       CLK_ETHIF,
+       CLK_VDEC,
+       CLK_HIFSEL,
+       CLK_JPGDEC,
+       CLK_AUDIO,
+       CLK_MAX,
+};
+
+static const char * const clk_names[] = {
+       NULL,
+       "mm",
+       "mfg",
+       "venc",
+       "venc_lt",
+       "ethif",
+       "vdec",
+       "hif_sel",
+       "jpgdec",
+       "audio",
+       NULL,
+};
+
+#define MAX_CLKS       3
+
+/**
+ * struct scp_domain_data - scp domain data for power on/off flow
+ * @name: The domain name.
+ * @sta_mask: The mask for power on/off status bit.
+ * @ctl_offs: The offset for main power control register.
+ * @sram_pdn_bits: The mask for sram power control bits.
+ * @sram_pdn_ack_bits: The mask for sram power control acked bits.
+ * @bus_prot_mask: The mask for single step bus protection.
+ * @clk_id: The basic clocks required by this power domain.
+ * @caps: The flag for active wake-up action.
+ */
+struct scp_domain_data {
+       const char *name;
+       u32 sta_mask;
+       int ctl_offs;
+       u32 sram_pdn_bits;
+       u32 sram_pdn_ack_bits;
+       u32 bus_prot_mask;
+       enum clk_id clk_id[MAX_CLKS];
+       u8 caps;
+};
+
+struct scp;
+
+struct scp_domain {
+       struct generic_pm_domain genpd;
+       struct scp *scp;
+       struct clk *clk[MAX_CLKS];
+       const struct scp_domain_data *data;
+       struct regulator *supply;
+};
+
+struct scp_ctrl_reg {
+       int pwr_sta_offs;
+       int pwr_sta2nd_offs;
+};
+
+struct scp {
+       struct scp_domain *domains;
+       struct genpd_onecell_data pd_data;
+       struct device *dev;
+       void __iomem *base;
+       struct regmap *infracfg;
+       struct scp_ctrl_reg ctrl_reg;
+       bool bus_prot_reg_update;
+};
+
+struct scp_subdomain {
+       int origin;
+       int subdomain;
+};
+
+struct scp_soc_data {
+       const struct scp_domain_data *domains;
+       int num_domains;
+       const struct scp_subdomain *subdomains;
+       int num_subdomains;
+       const struct scp_ctrl_reg regs;
+       bool bus_prot_reg_update;
+};
+
+static int scpsys_domain_is_on(struct scp_domain *scpd)
+{
+       struct scp *scp = scpd->scp;
+
+       u32 status = readl(scp->base + scp->ctrl_reg.pwr_sta_offs) &
+                                               scpd->data->sta_mask;
+       u32 status2 = readl(scp->base + scp->ctrl_reg.pwr_sta2nd_offs) &
+                                               scpd->data->sta_mask;
+
+       /*
+        * A domain is on when both status bits are set. If only one is set
+        * return an error. This happens while powering up a domain
+        */
+
+       if (status && status2)
+               return true;
+       if (!status && !status2)
+               return false;
+
+       return -EINVAL;
+}
+
+static int scpsys_regulator_enable(struct scp_domain *scpd)
+{
+       if (!scpd->supply)
+               return 0;
+
+       return regulator_enable(scpd->supply);
+}
+
+static int scpsys_regulator_disable(struct scp_domain *scpd)
+{
+       if (!scpd->supply)
+               return 0;
+
+       return regulator_disable(scpd->supply);
+}
+
+static void scpsys_clk_disable(struct clk *clk[], int max_num)
+{
+       int i;
+
+       for (i = max_num - 1; i >= 0; i--)
+               clk_disable_unprepare(clk[i]);
+}
+
+static int scpsys_clk_enable(struct clk *clk[], int max_num)
+{
+       int i, ret = 0;
+
+       for (i = 0; i < max_num && clk[i]; i++) {
+               ret = clk_prepare_enable(clk[i]);
+               if (ret) {
+                       scpsys_clk_disable(clk, i);
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+static int scpsys_sram_enable(struct scp_domain *scpd, void __iomem *ctl_addr)
+{
+       u32 val;
+       u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
+       int tmp;
+
+       val = readl(ctl_addr);
+       val &= ~scpd->data->sram_pdn_bits;
+       writel(val, ctl_addr);
+
+       /* Either wait until SRAM_PDN_ACK all 0 or have a force wait */
+       if (MTK_SCPD_CAPS(scpd, MTK_SCPD_FWAIT_SRAM)) {
+               /*
+                * Currently, MTK_SCPD_FWAIT_SRAM is necessary only for
+                * MT7622_POWER_DOMAIN_WB and thus just a trivial setup
+                * is applied here.
+                */
+               usleep_range(12000, 12100);
+       } else {
+               /* Either wait until SRAM_PDN_ACK all 1 or 0 */
+               int ret = readl_poll_timeout(ctl_addr, tmp,
+                               (tmp & pdn_ack) == 0,
+                               MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int scpsys_sram_disable(struct scp_domain *scpd, void __iomem *ctl_addr)
+{
+       u32 val;
+       u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
+       int tmp;
+
+       val = readl(ctl_addr);
+       val |= scpd->data->sram_pdn_bits;
+       writel(val, ctl_addr);
+
+       /* Either wait until SRAM_PDN_ACK all 1 or 0 */
+       return readl_poll_timeout(ctl_addr, tmp,
+                       (tmp & pdn_ack) == pdn_ack,
+                       MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+}
+
+static int scpsys_bus_protect_enable(struct scp_domain *scpd)
+{
+       struct scp *scp = scpd->scp;
+
+       if (!scpd->data->bus_prot_mask)
+               return 0;
+
+       return mtk_infracfg_set_bus_protection(scp->infracfg,
+                       scpd->data->bus_prot_mask,
+                       scp->bus_prot_reg_update);
+}
+
+static int scpsys_bus_protect_disable(struct scp_domain *scpd)
+{
+       struct scp *scp = scpd->scp;
+
+       if (!scpd->data->bus_prot_mask)
+               return 0;
+
+       return mtk_infracfg_clear_bus_protection(scp->infracfg,
+                       scpd->data->bus_prot_mask,
+                       scp->bus_prot_reg_update);
+}
+
+static int scpsys_power_on(struct generic_pm_domain *genpd)
+{
+       struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
+       struct scp *scp = scpd->scp;
+       void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
+       u32 val;
+       int ret, tmp;
+
+       ret = scpsys_regulator_enable(scpd);
+       if (ret < 0)
+               return ret;
+
+       ret = scpsys_clk_enable(scpd->clk, MAX_CLKS);
+       if (ret)
+               goto err_clk;
+
+       /* subsys power on */
+       val = readl(ctl_addr);
+       val |= PWR_ON_BIT;
+       writel(val, ctl_addr);
+       val |= PWR_ON_2ND_BIT;
+       writel(val, ctl_addr);
+
+       /* wait until PWR_ACK = 1 */
+       ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp > 0,
+                                MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+       if (ret < 0)
+               goto err_pwr_ack;
+
+       val &= ~PWR_CLK_DIS_BIT;
+       writel(val, ctl_addr);
+
+       val &= ~PWR_ISO_BIT;
+       writel(val, ctl_addr);
+
+       val |= PWR_RST_B_BIT;
+       writel(val, ctl_addr);
+
+       ret = scpsys_sram_enable(scpd, ctl_addr);
+       if (ret < 0)
+               goto err_pwr_ack;
+
+       ret = scpsys_bus_protect_disable(scpd);
+       if (ret < 0)
+               goto err_pwr_ack;
+
+       return 0;
+
+err_pwr_ack:
+       scpsys_clk_disable(scpd->clk, MAX_CLKS);
+err_clk:
+       scpsys_regulator_disable(scpd);
+
+       dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
+
+       return ret;
+}
+
+static int scpsys_power_off(struct generic_pm_domain *genpd)
+{
+       struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
+       struct scp *scp = scpd->scp;
+       void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
+       u32 val;
+       int ret, tmp;
+
+       ret = scpsys_bus_protect_enable(scpd);
+       if (ret < 0)
+               goto out;
+
+       ret = scpsys_sram_disable(scpd, ctl_addr);
+       if (ret < 0)
+               goto out;
+
+       /* subsys power off */
+       val = readl(ctl_addr);
+       val |= PWR_ISO_BIT;
+       writel(val, ctl_addr);
+
+       val &= ~PWR_RST_B_BIT;
+       writel(val, ctl_addr);
+
+       val |= PWR_CLK_DIS_BIT;
+       writel(val, ctl_addr);
+
+       val &= ~PWR_ON_BIT;
+       writel(val, ctl_addr);
+
+       val &= ~PWR_ON_2ND_BIT;
+       writel(val, ctl_addr);
+
+       /* wait until PWR_ACK = 0 */
+       ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp == 0,
+                                MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+       if (ret < 0)
+               goto out;
+
+       scpsys_clk_disable(scpd->clk, MAX_CLKS);
+
+       ret = scpsys_regulator_disable(scpd);
+       if (ret < 0)
+               goto out;
+
+       return 0;
+
+out:
+       dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name);
+
+       return ret;
+}
+
+static void init_clks(struct platform_device *pdev, struct clk **clk)
+{
+       int i;
+
+       for (i = CLK_NONE + 1; i < CLK_MAX; i++)
+               clk[i] = devm_clk_get(&pdev->dev, clk_names[i]);
+}
+
+static struct scp *init_scp(struct platform_device *pdev,
+                       const struct scp_domain_data *scp_domain_data, int num,
+                       const struct scp_ctrl_reg *scp_ctrl_reg,
+                       bool bus_prot_reg_update)
+{
+       struct genpd_onecell_data *pd_data;
+       struct resource *res;
+       int i, j;
+       struct scp *scp;
+       struct clk *clk[CLK_MAX];
+
+       scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL);
+       if (!scp)
+               return ERR_PTR(-ENOMEM);
+
+       scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs;
+       scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs;
+
+       scp->bus_prot_reg_update = bus_prot_reg_update;
+
+       scp->dev = &pdev->dev;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       scp->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(scp->base))
+               return ERR_CAST(scp->base);
+
+       scp->domains = devm_kcalloc(&pdev->dev,
+                               num, sizeof(*scp->domains), GFP_KERNEL);
+       if (!scp->domains)
+               return ERR_PTR(-ENOMEM);
+
+       pd_data = &scp->pd_data;
+
+       pd_data->domains = devm_kcalloc(&pdev->dev,
+                       num, sizeof(*pd_data->domains), GFP_KERNEL);
+       if (!pd_data->domains)
+               return ERR_PTR(-ENOMEM);
+
+       scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+                       "infracfg");
+       if (IS_ERR(scp->infracfg)) {
+               dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n",
+                               PTR_ERR(scp->infracfg));
+               return ERR_CAST(scp->infracfg);
+       }
+
+       for (i = 0; i < num; i++) {
+               struct scp_domain *scpd = &scp->domains[i];
+               const struct scp_domain_data *data = &scp_domain_data[i];
+
+               scpd->supply = devm_regulator_get_optional(&pdev->dev, data->name);
+               if (IS_ERR(scpd->supply)) {
+                       if (PTR_ERR(scpd->supply) == -ENODEV)
+                               scpd->supply = NULL;
+                       else
+                               return ERR_CAST(scpd->supply);
+               }
+       }
+
+       pd_data->num_domains = num;
+
+       init_clks(pdev, clk);
+
+       for (i = 0; i < num; i++) {
+               struct scp_domain *scpd = &scp->domains[i];
+               struct generic_pm_domain *genpd = &scpd->genpd;
+               const struct scp_domain_data *data = &scp_domain_data[i];
+
+               pd_data->domains[i] = genpd;
+               scpd->scp = scp;
+
+               scpd->data = data;
+
+               for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) {
+                       struct clk *c = clk[data->clk_id[j]];
+
+                       if (IS_ERR(c)) {
+                               dev_err(&pdev->dev, "%s: clk unavailable\n",
+                                       data->name);
+                               return ERR_CAST(c);
+                       }
+
+                       scpd->clk[j] = c;
+               }
+
+               genpd->name = data->name;
+               genpd->power_off = scpsys_power_off;
+               genpd->power_on = scpsys_power_on;
+               if (MTK_SCPD_CAPS(scpd, MTK_SCPD_ACTIVE_WAKEUP))
+                       genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP;
+       }
+
+       return scp;
+}
+
+static void mtk_register_power_domains(struct platform_device *pdev,
+                               struct scp *scp, int num)
+{
+       struct genpd_onecell_data *pd_data;
+       int i, ret;
+
+       for (i = 0; i < num; i++) {
+               struct scp_domain *scpd = &scp->domains[i];
+               struct generic_pm_domain *genpd = &scpd->genpd;
+               bool on;
+
+               /*
+                * Initially turn on all domains to make the domains usable
+                * with !CONFIG_PM and to get the hardware in sync with the
+                * software.  The unused domains will be switched off during
+                * late_init time.
+                */
+               on = !WARN_ON(genpd->power_on(genpd) < 0);
+
+               pm_genpd_init(genpd, NULL, !on);
+       }
+
+       /*
+        * We are not allowed to fail here since there is no way to unregister
+        * a power domain. Once registered above we have to keep the domains
+        * valid.
+        */
+
+       pd_data = &scp->pd_data;
+
+       ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data);
+       if (ret)
+               dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
+}
+
+/*
+ * MT2701 power domain support
+ */
+
+static const struct scp_domain_data scp_domain_data_mt2701[] = {
+       [MT2701_POWER_DOMAIN_CONN] = {
+               .name = "conn",
+               .sta_mask = PWR_STATUS_CONN,
+               .ctl_offs = SPM_CONN_PWR_CON,
+               .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M |
+                                MT2701_TOP_AXI_PROT_EN_CONN_S,
+               .clk_id = {CLK_NONE},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2701_POWER_DOMAIN_DISP] = {
+               .name = "disp",
+               .sta_mask = PWR_STATUS_DISP,
+               .ctl_offs = SPM_DIS_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .clk_id = {CLK_MM},
+               .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_MM_M0,
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2701_POWER_DOMAIN_MFG] = {
+               .name = "mfg",
+               .sta_mask = PWR_STATUS_MFG,
+               .ctl_offs = SPM_MFG_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .clk_id = {CLK_MFG},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2701_POWER_DOMAIN_VDEC] = {
+               .name = "vdec",
+               .sta_mask = PWR_STATUS_VDEC,
+               .ctl_offs = SPM_VDE_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .clk_id = {CLK_MM},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2701_POWER_DOMAIN_ISP] = {
+               .name = "isp",
+               .sta_mask = PWR_STATUS_ISP,
+               .ctl_offs = SPM_ISP_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(13, 12),
+               .clk_id = {CLK_MM},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2701_POWER_DOMAIN_BDP] = {
+               .name = "bdp",
+               .sta_mask = PWR_STATUS_BDP,
+               .ctl_offs = SPM_BDP_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .clk_id = {CLK_NONE},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2701_POWER_DOMAIN_ETH] = {
+               .name = "eth",
+               .sta_mask = PWR_STATUS_ETH,
+               .ctl_offs = SPM_ETH_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .clk_id = {CLK_ETHIF},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2701_POWER_DOMAIN_HIF] = {
+               .name = "hif",
+               .sta_mask = PWR_STATUS_HIF,
+               .ctl_offs = SPM_HIF_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .clk_id = {CLK_ETHIF},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2701_POWER_DOMAIN_IFR_MSC] = {
+               .name = "ifr_msc",
+               .sta_mask = PWR_STATUS_IFR_MSC,
+               .ctl_offs = SPM_IFR_MSC_PWR_CON,
+               .clk_id = {CLK_NONE},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+};
+
+/*
+ * MT2712 power domain support
+ */
+static const struct scp_domain_data scp_domain_data_mt2712[] = {
+       [MT2712_POWER_DOMAIN_MM] = {
+               .name = "mm",
+               .sta_mask = PWR_STATUS_DISP,
+               .ctl_offs = SPM_DIS_PWR_CON,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .clk_id = {CLK_MM},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2712_POWER_DOMAIN_VDEC] = {
+               .name = "vdec",
+               .sta_mask = PWR_STATUS_VDEC,
+               .ctl_offs = SPM_VDE_PWR_CON,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .clk_id = {CLK_MM, CLK_VDEC},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2712_POWER_DOMAIN_VENC] = {
+               .name = "venc",
+               .sta_mask = PWR_STATUS_VENC,
+               .ctl_offs = SPM_VEN_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .clk_id = {CLK_MM, CLK_VENC, CLK_JPGDEC},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2712_POWER_DOMAIN_ISP] = {
+               .name = "isp",
+               .sta_mask = PWR_STATUS_ISP,
+               .ctl_offs = SPM_ISP_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(13, 12),
+               .clk_id = {CLK_MM},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2712_POWER_DOMAIN_AUDIO] = {
+               .name = "audio",
+               .sta_mask = PWR_STATUS_AUDIO,
+               .ctl_offs = SPM_AUDIO_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .clk_id = {CLK_AUDIO},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2712_POWER_DOMAIN_USB] = {
+               .name = "usb",
+               .sta_mask = PWR_STATUS_USB,
+               .ctl_offs = SPM_USB_PWR_CON,
+               .sram_pdn_bits = GENMASK(10, 8),
+               .sram_pdn_ack_bits = GENMASK(14, 12),
+               .clk_id = {CLK_NONE},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2712_POWER_DOMAIN_USB2] = {
+               .name = "usb2",
+               .sta_mask = PWR_STATUS_USB2,
+               .ctl_offs = SPM_USB2_PWR_CON,
+               .sram_pdn_bits = GENMASK(10, 8),
+               .sram_pdn_ack_bits = GENMASK(14, 12),
+               .clk_id = {CLK_NONE},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2712_POWER_DOMAIN_MFG] = {
+               .name = "mfg",
+               .sta_mask = PWR_STATUS_MFG,
+               .ctl_offs = SPM_MFG_PWR_CON,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(16, 16),
+               .clk_id = {CLK_MFG},
+               .bus_prot_mask = BIT(14) | BIT(21) | BIT(23),
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2712_POWER_DOMAIN_MFG_SC1] = {
+               .name = "mfg_sc1",
+               .sta_mask = BIT(22),
+               .ctl_offs = 0x02c0,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(16, 16),
+               .clk_id = {CLK_NONE},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2712_POWER_DOMAIN_MFG_SC2] = {
+               .name = "mfg_sc2",
+               .sta_mask = BIT(23),
+               .ctl_offs = 0x02c4,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(16, 16),
+               .clk_id = {CLK_NONE},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT2712_POWER_DOMAIN_MFG_SC3] = {
+               .name = "mfg_sc3",
+               .sta_mask = BIT(30),
+               .ctl_offs = 0x01f8,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(16, 16),
+               .clk_id = {CLK_NONE},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+};
+
+static const struct scp_subdomain scp_subdomain_mt2712[] = {
+       {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_VDEC},
+       {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_VENC},
+       {MT2712_POWER_DOMAIN_MM, MT2712_POWER_DOMAIN_ISP},
+       {MT2712_POWER_DOMAIN_MFG, MT2712_POWER_DOMAIN_MFG_SC1},
+       {MT2712_POWER_DOMAIN_MFG_SC1, MT2712_POWER_DOMAIN_MFG_SC2},
+       {MT2712_POWER_DOMAIN_MFG_SC2, MT2712_POWER_DOMAIN_MFG_SC3},
+};
+
+/*
+ * MT6797 power domain support
+ */
+
+static const struct scp_domain_data scp_domain_data_mt6797[] = {
+       [MT6797_POWER_DOMAIN_VDEC] = {
+               .name = "vdec",
+               .sta_mask = BIT(7),
+               .ctl_offs = 0x300,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .clk_id = {CLK_VDEC},
+       },
+       [MT6797_POWER_DOMAIN_VENC] = {
+               .name = "venc",
+               .sta_mask = BIT(21),
+               .ctl_offs = 0x304,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .clk_id = {CLK_NONE},
+       },
+       [MT6797_POWER_DOMAIN_ISP] = {
+               .name = "isp",
+               .sta_mask = BIT(5),
+               .ctl_offs = 0x308,
+               .sram_pdn_bits = GENMASK(9, 8),
+               .sram_pdn_ack_bits = GENMASK(13, 12),
+               .clk_id = {CLK_NONE},
+       },
+       [MT6797_POWER_DOMAIN_MM] = {
+               .name = "mm",
+               .sta_mask = BIT(3),
+               .ctl_offs = 0x30C,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .clk_id = {CLK_MM},
+               .bus_prot_mask = (BIT(1) | BIT(2)),
+       },
+       [MT6797_POWER_DOMAIN_AUDIO] = {
+               .name = "audio",
+               .sta_mask = BIT(24),
+               .ctl_offs = 0x314,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .clk_id = {CLK_NONE},
+       },
+       [MT6797_POWER_DOMAIN_MFG_ASYNC] = {
+               .name = "mfg_async",
+               .sta_mask = BIT(13),
+               .ctl_offs = 0x334,
+               .sram_pdn_bits = 0,
+               .sram_pdn_ack_bits = 0,
+               .clk_id = {CLK_MFG},
+       },
+       [MT6797_POWER_DOMAIN_MJC] = {
+               .name = "mjc",
+               .sta_mask = BIT(20),
+               .ctl_offs = 0x310,
+               .sram_pdn_bits = GENMASK(8, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .clk_id = {CLK_NONE},
+       },
+};
+
+#define SPM_PWR_STATUS_MT6797          0x0180
+#define SPM_PWR_STATUS_2ND_MT6797      0x0184
+
+static const struct scp_subdomain scp_subdomain_mt6797[] = {
+       {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VDEC},
+       {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_ISP},
+       {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VENC},
+       {MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_MJC},
+};
+
+/*
+ * MT7622 power domain support
+ */
+
+static const struct scp_domain_data scp_domain_data_mt7622[] = {
+       [MT7622_POWER_DOMAIN_ETHSYS] = {
+               .name = "ethsys",
+               .sta_mask = PWR_STATUS_ETHSYS,
+               .ctl_offs = SPM_ETHSYS_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .clk_id = {CLK_NONE},
+               .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_ETHSYS,
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT7622_POWER_DOMAIN_HIF0] = {
+               .name = "hif0",
+               .sta_mask = PWR_STATUS_HIF0,
+               .ctl_offs = SPM_HIF0_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .clk_id = {CLK_HIFSEL},
+               .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF0,
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT7622_POWER_DOMAIN_HIF1] = {
+               .name = "hif1",
+               .sta_mask = PWR_STATUS_HIF1,
+               .ctl_offs = SPM_HIF1_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .clk_id = {CLK_HIFSEL},
+               .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF1,
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT7622_POWER_DOMAIN_WB] = {
+               .name = "wb",
+               .sta_mask = PWR_STATUS_WB,
+               .ctl_offs = SPM_WB_PWR_CON,
+               .sram_pdn_bits = 0,
+               .sram_pdn_ack_bits = 0,
+               .clk_id = {CLK_NONE},
+               .bus_prot_mask = MT7622_TOP_AXI_PROT_EN_WB,
+               .caps = MTK_SCPD_ACTIVE_WAKEUP | MTK_SCPD_FWAIT_SRAM,
+       },
+};
+
+/*
+ * MT7623A power domain support
+ */
+
+static const struct scp_domain_data scp_domain_data_mt7623a[] = {
+       [MT7623A_POWER_DOMAIN_CONN] = {
+               .name = "conn",
+               .sta_mask = PWR_STATUS_CONN,
+               .ctl_offs = SPM_CONN_PWR_CON,
+               .bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M |
+                                MT2701_TOP_AXI_PROT_EN_CONN_S,
+               .clk_id = {CLK_NONE},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT7623A_POWER_DOMAIN_ETH] = {
+               .name = "eth",
+               .sta_mask = PWR_STATUS_ETH,
+               .ctl_offs = SPM_ETH_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .clk_id = {CLK_ETHIF},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT7623A_POWER_DOMAIN_HIF] = {
+               .name = "hif",
+               .sta_mask = PWR_STATUS_HIF,
+               .ctl_offs = SPM_HIF_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .clk_id = {CLK_ETHIF},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT7623A_POWER_DOMAIN_IFR_MSC] = {
+               .name = "ifr_msc",
+               .sta_mask = PWR_STATUS_IFR_MSC,
+               .ctl_offs = SPM_IFR_MSC_PWR_CON,
+               .clk_id = {CLK_NONE},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+};
+
+/*
+ * MT8173 power domain support
+ */
+
+static const struct scp_domain_data scp_domain_data_mt8173[] = {
+       [MT8173_POWER_DOMAIN_VDEC] = {
+               .name = "vdec",
+               .sta_mask = PWR_STATUS_VDEC,
+               .ctl_offs = SPM_VDE_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .clk_id = {CLK_MM},
+       },
+       [MT8173_POWER_DOMAIN_VENC] = {
+               .name = "venc",
+               .sta_mask = PWR_STATUS_VENC,
+               .ctl_offs = SPM_VEN_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .clk_id = {CLK_MM, CLK_VENC},
+       },
+       [MT8173_POWER_DOMAIN_ISP] = {
+               .name = "isp",
+               .sta_mask = PWR_STATUS_ISP,
+               .ctl_offs = SPM_ISP_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(13, 12),
+               .clk_id = {CLK_MM},
+       },
+       [MT8173_POWER_DOMAIN_MM] = {
+               .name = "mm",
+               .sta_mask = PWR_STATUS_DISP,
+               .ctl_offs = SPM_DIS_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(12, 12),
+               .clk_id = {CLK_MM},
+               .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
+                       MT8173_TOP_AXI_PROT_EN_MM_M1,
+       },
+       [MT8173_POWER_DOMAIN_VENC_LT] = {
+               .name = "venc_lt",
+               .sta_mask = PWR_STATUS_VENC_LT,
+               .ctl_offs = SPM_VEN2_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .clk_id = {CLK_MM, CLK_VENC_LT},
+       },
+       [MT8173_POWER_DOMAIN_AUDIO] = {
+               .name = "audio",
+               .sta_mask = PWR_STATUS_AUDIO,
+               .ctl_offs = SPM_AUDIO_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .clk_id = {CLK_NONE},
+       },
+       [MT8173_POWER_DOMAIN_USB] = {
+               .name = "usb",
+               .sta_mask = PWR_STATUS_USB,
+               .ctl_offs = SPM_USB_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(15, 12),
+               .clk_id = {CLK_NONE},
+               .caps = MTK_SCPD_ACTIVE_WAKEUP,
+       },
+       [MT8173_POWER_DOMAIN_MFG_ASYNC] = {
+               .name = "mfg_async",
+               .sta_mask = PWR_STATUS_MFG_ASYNC,
+               .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = 0,
+               .clk_id = {CLK_MFG},
+       },
+       [MT8173_POWER_DOMAIN_MFG_2D] = {
+               .name = "mfg_2d",
+               .sta_mask = PWR_STATUS_MFG_2D,
+               .ctl_offs = SPM_MFG_2D_PWR_CON,
+               .sram_pdn_bits = GENMASK(11, 8),
+               .sram_pdn_ack_bits = GENMASK(13, 12),
+               .clk_id = {CLK_NONE},
+       },
+       [MT8173_POWER_DOMAIN_MFG] = {
+               .name = "mfg",
+               .sta_mask = PWR_STATUS_MFG,
+               .ctl_offs = SPM_MFG_PWR_CON,
+               .sram_pdn_bits = GENMASK(13, 8),
+               .sram_pdn_ack_bits = GENMASK(21, 16),
+               .clk_id = {CLK_NONE},
+               .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
+                       MT8173_TOP_AXI_PROT_EN_MFG_M0 |
+                       MT8173_TOP_AXI_PROT_EN_MFG_M1 |
+                       MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT,
+       },
+};
+
+static const struct scp_subdomain scp_subdomain_mt8173[] = {
+       {MT8173_POWER_DOMAIN_MFG_ASYNC, MT8173_POWER_DOMAIN_MFG_2D},
+       {MT8173_POWER_DOMAIN_MFG_2D, MT8173_POWER_DOMAIN_MFG},
+};
+
+static const struct scp_soc_data mt2701_data = {
+       .domains = scp_domain_data_mt2701,
+       .num_domains = ARRAY_SIZE(scp_domain_data_mt2701),
+       .regs = {
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+       },
+       .bus_prot_reg_update = true,
+};
+
+static const struct scp_soc_data mt2712_data = {
+       .domains = scp_domain_data_mt2712,
+       .num_domains = ARRAY_SIZE(scp_domain_data_mt2712),
+       .subdomains = scp_subdomain_mt2712,
+       .num_subdomains = ARRAY_SIZE(scp_subdomain_mt2712),
+       .regs = {
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+       },
+       .bus_prot_reg_update = false,
+};
+
+static const struct scp_soc_data mt6797_data = {
+       .domains = scp_domain_data_mt6797,
+       .num_domains = ARRAY_SIZE(scp_domain_data_mt6797),
+       .subdomains = scp_subdomain_mt6797,
+       .num_subdomains = ARRAY_SIZE(scp_subdomain_mt6797),
+       .regs = {
+               .pwr_sta_offs = SPM_PWR_STATUS_MT6797,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
+       },
+       .bus_prot_reg_update = true,
+};
+
+static const struct scp_soc_data mt7622_data = {
+       .domains = scp_domain_data_mt7622,
+       .num_domains = ARRAY_SIZE(scp_domain_data_mt7622),
+       .regs = {
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+       },
+       .bus_prot_reg_update = true,
+};
+
+static const struct scp_soc_data mt7623a_data = {
+       .domains = scp_domain_data_mt7623a,
+       .num_domains = ARRAY_SIZE(scp_domain_data_mt7623a),
+       .regs = {
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+       },
+       .bus_prot_reg_update = true,
+};
+
+static const struct scp_soc_data mt8173_data = {
+       .domains = scp_domain_data_mt8173,
+       .num_domains = ARRAY_SIZE(scp_domain_data_mt8173),
+       .subdomains = scp_subdomain_mt8173,
+       .num_subdomains = ARRAY_SIZE(scp_subdomain_mt8173),
+       .regs = {
+               .pwr_sta_offs = SPM_PWR_STATUS,
+               .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
+       },
+       .bus_prot_reg_update = true,
+};
+
+/*
+ * scpsys driver init
+ */
+
+static const struct of_device_id of_scpsys_match_tbl[] = {
+       {
+               .compatible = "mediatek,mt2701-scpsys",
+               .data = &mt2701_data,
+       }, {
+               .compatible = "mediatek,mt2712-scpsys",
+               .data = &mt2712_data,
+       }, {
+               .compatible = "mediatek,mt6797-scpsys",
+               .data = &mt6797_data,
+       }, {
+               .compatible = "mediatek,mt7622-scpsys",
+               .data = &mt7622_data,
+       }, {
+               .compatible = "mediatek,mt7623a-scpsys",
+               .data = &mt7623a_data,
+       }, {
+               .compatible = "mediatek,mt8173-scpsys",
+               .data = &mt8173_data,
+       }, {
+               /* sentinel */
+       }
+};
+
+static int scpsys_probe(struct platform_device *pdev)
+{
+       const struct scp_subdomain *sd;
+       const struct scp_soc_data *soc;
+       struct scp *scp;
+       struct genpd_onecell_data *pd_data;
+       int i, ret;
+
+       soc = of_device_get_match_data(&pdev->dev);
+
+       scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs,
+                       soc->bus_prot_reg_update);
+       if (IS_ERR(scp))
+               return PTR_ERR(scp);
+
+       mtk_register_power_domains(pdev, scp, soc->num_domains);
+
+       pd_data = &scp->pd_data;
+
+       for (i = 0, sd = soc->subdomains; i < soc->num_subdomains; i++, sd++) {
+               ret = pm_genpd_add_subdomain(pd_data->domains[sd->origin],
+                                            pd_data->domains[sd->subdomain]);
+               if (ret && IS_ENABLED(CONFIG_PM))
+                       dev_err(&pdev->dev, "Failed to add subdomain: %d\n",
+                               ret);
+       }
+
+       return 0;
+}
+
+static struct platform_driver scpsys_drv = {
+       .probe = scpsys_probe,
+       .driver = {
+               .name = "mtk-scpsys",
+               .suppress_bind_attrs = true,
+               .owner = THIS_MODULE,
+               .of_match_table = of_scpsys_match_tbl,
+       },
+};
+builtin_platform_driver(scpsys_drv);
diff --git a/drivers/pmdomain/qcom/Makefile b/drivers/pmdomain/qcom/Makefile
new file mode 100644 (file)
index 0000000..403dfc5
--- /dev/null
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_QCOM_CPR)         += cpr.o
+obj-$(CONFIG_QCOM_RPMPD)       += rpmpd.o
+obj-$(CONFIG_QCOM_RPMHPD)      += rpmhpd.o
diff --git a/drivers/pmdomain/qcom/cpr.c b/drivers/pmdomain/qcom/cpr.c
new file mode 100644 (file)
index 0000000..94a3f09
--- /dev/null
@@ -0,0 +1,1756 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019, Linaro Limited
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/debugfs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_opp.h>
+#include <linux/interrupt.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
+#include <linux/nvmem-consumer.h>
+
+/* Register Offsets for RB-CPR and Bit Definitions */
+
+/* RBCPR Version Register */
+#define REG_RBCPR_VERSION              0
+#define RBCPR_VER_2                    0x02
+#define FLAGS_IGNORE_1ST_IRQ_STATUS    BIT(0)
+
+/* RBCPR Gate Count and Target Registers */
+#define REG_RBCPR_GCNT_TARGET(n)       (0x60 + 4 * (n))
+
+#define RBCPR_GCNT_TARGET_TARGET_SHIFT 0
+#define RBCPR_GCNT_TARGET_TARGET_MASK  GENMASK(11, 0)
+#define RBCPR_GCNT_TARGET_GCNT_SHIFT   12
+#define RBCPR_GCNT_TARGET_GCNT_MASK    GENMASK(9, 0)
+
+/* RBCPR Timer Control */
+#define REG_RBCPR_TIMER_INTERVAL       0x44
+#define REG_RBIF_TIMER_ADJUST          0x4c
+
+#define RBIF_TIMER_ADJ_CONS_UP_MASK    GENMASK(3, 0)
+#define RBIF_TIMER_ADJ_CONS_UP_SHIFT   0
+#define RBIF_TIMER_ADJ_CONS_DOWN_MASK  GENMASK(3, 0)
+#define RBIF_TIMER_ADJ_CONS_DOWN_SHIFT 4
+#define RBIF_TIMER_ADJ_CLAMP_INT_MASK  GENMASK(7, 0)
+#define RBIF_TIMER_ADJ_CLAMP_INT_SHIFT 8
+
+/* RBCPR Config Register */
+#define REG_RBIF_LIMIT                 0x48
+#define RBIF_LIMIT_CEILING_MASK                GENMASK(5, 0)
+#define RBIF_LIMIT_CEILING_SHIFT       6
+#define RBIF_LIMIT_FLOOR_BITS          6
+#define RBIF_LIMIT_FLOOR_MASK          GENMASK(5, 0)
+
+#define RBIF_LIMIT_CEILING_DEFAULT     RBIF_LIMIT_CEILING_MASK
+#define RBIF_LIMIT_FLOOR_DEFAULT       0
+
+#define REG_RBIF_SW_VLEVEL             0x94
+#define RBIF_SW_VLEVEL_DEFAULT         0x20
+
+#define REG_RBCPR_STEP_QUOT            0x80
+#define RBCPR_STEP_QUOT_STEPQUOT_MASK  GENMASK(7, 0)
+#define RBCPR_STEP_QUOT_IDLE_CLK_MASK  GENMASK(3, 0)
+#define RBCPR_STEP_QUOT_IDLE_CLK_SHIFT 8
+
+/* RBCPR Control Register */
+#define REG_RBCPR_CTL                  0x90
+
+#define RBCPR_CTL_LOOP_EN                      BIT(0)
+#define RBCPR_CTL_TIMER_EN                     BIT(3)
+#define RBCPR_CTL_SW_AUTO_CONT_ACK_EN          BIT(5)
+#define RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN      BIT(6)
+#define RBCPR_CTL_COUNT_MODE                   BIT(10)
+#define RBCPR_CTL_UP_THRESHOLD_MASK    GENMASK(3, 0)
+#define RBCPR_CTL_UP_THRESHOLD_SHIFT   24
+#define RBCPR_CTL_DN_THRESHOLD_MASK    GENMASK(3, 0)
+#define RBCPR_CTL_DN_THRESHOLD_SHIFT   28
+
+/* RBCPR Ack/Nack Response */
+#define REG_RBIF_CONT_ACK_CMD          0x98
+#define REG_RBIF_CONT_NACK_CMD         0x9c
+
+/* RBCPR Result status Register */
+#define REG_RBCPR_RESULT_0             0xa0
+
+#define RBCPR_RESULT0_BUSY_SHIFT       19
+#define RBCPR_RESULT0_BUSY_MASK                BIT(RBCPR_RESULT0_BUSY_SHIFT)
+#define RBCPR_RESULT0_ERROR_LT0_SHIFT  18
+#define RBCPR_RESULT0_ERROR_SHIFT      6
+#define RBCPR_RESULT0_ERROR_MASK       GENMASK(11, 0)
+#define RBCPR_RESULT0_ERROR_STEPS_SHIFT        2
+#define RBCPR_RESULT0_ERROR_STEPS_MASK GENMASK(3, 0)
+#define RBCPR_RESULT0_STEP_UP_SHIFT    1
+
+/* RBCPR Interrupt Control Register */
+#define REG_RBIF_IRQ_EN(n)             (0x100 + 4 * (n))
+#define REG_RBIF_IRQ_CLEAR             0x110
+#define REG_RBIF_IRQ_STATUS            0x114
+
+#define CPR_INT_DONE           BIT(0)
+#define CPR_INT_MIN            BIT(1)
+#define CPR_INT_DOWN           BIT(2)
+#define CPR_INT_MID            BIT(3)
+#define CPR_INT_UP             BIT(4)
+#define CPR_INT_MAX            BIT(5)
+#define CPR_INT_CLAMP          BIT(6)
+#define CPR_INT_ALL    (CPR_INT_DONE | CPR_INT_MIN | CPR_INT_DOWN | \
+                       CPR_INT_MID | CPR_INT_UP | CPR_INT_MAX | CPR_INT_CLAMP)
+#define CPR_INT_DEFAULT        (CPR_INT_UP | CPR_INT_DOWN)
+
+#define CPR_NUM_RING_OSC       8
+
+/* CPR eFuse parameters */
+#define CPR_FUSE_TARGET_QUOT_BITS_MASK GENMASK(11, 0)
+
+#define CPR_FUSE_MIN_QUOT_DIFF         50
+
+#define FUSE_REVISION_UNKNOWN          (-1)
+
+enum voltage_change_dir {
+       NO_CHANGE,
+       DOWN,
+       UP,
+};
+
+struct cpr_fuse {
+       char *ring_osc;
+       char *init_voltage;
+       char *quotient;
+       char *quotient_offset;
+};
+
+struct fuse_corner_data {
+       int ref_uV;
+       int max_uV;
+       int min_uV;
+       int max_volt_scale;
+       int max_quot_scale;
+       /* fuse quot */
+       int quot_offset;
+       int quot_scale;
+       int quot_adjust;
+       /* fuse quot_offset */
+       int quot_offset_scale;
+       int quot_offset_adjust;
+};
+
+struct cpr_fuses {
+       int init_voltage_step;
+       int init_voltage_width;
+       struct fuse_corner_data *fuse_corner_data;
+};
+
+struct corner_data {
+       unsigned int fuse_corner;
+       unsigned long freq;
+};
+
+struct cpr_desc {
+       unsigned int num_fuse_corners;
+       int min_diff_quot;
+       int *step_quot;
+
+       unsigned int            timer_delay_us;
+       unsigned int            timer_cons_up;
+       unsigned int            timer_cons_down;
+       unsigned int            up_threshold;
+       unsigned int            down_threshold;
+       unsigned int            idle_clocks;
+       unsigned int            gcnt_us;
+       unsigned int            vdd_apc_step_up_limit;
+       unsigned int            vdd_apc_step_down_limit;
+       unsigned int            clamp_timer_interval;
+
+       struct cpr_fuses cpr_fuses;
+       bool reduce_to_fuse_uV;
+       bool reduce_to_corner_uV;
+};
+
+struct acc_desc {
+       unsigned int    enable_reg;
+       u32             enable_mask;
+
+       struct reg_sequence     *config;
+       struct reg_sequence     *settings;
+       int                     num_regs_per_fuse;
+};
+
+struct cpr_acc_desc {
+       const struct cpr_desc *cpr_desc;
+       const struct acc_desc *acc_desc;
+};
+
+struct fuse_corner {
+       int min_uV;
+       int max_uV;
+       int uV;
+       int quot;
+       int step_quot;
+       const struct reg_sequence *accs;
+       int num_accs;
+       unsigned long max_freq;
+       u8 ring_osc_idx;
+};
+
+struct corner {
+       int min_uV;
+       int max_uV;
+       int uV;
+       int last_uV;
+       int quot_adjust;
+       u32 save_ctl;
+       u32 save_irq;
+       unsigned long freq;
+       struct fuse_corner *fuse_corner;
+};
+
+struct cpr_drv {
+       unsigned int            num_corners;
+       unsigned int            ref_clk_khz;
+
+       struct generic_pm_domain pd;
+       struct device           *dev;
+       struct device           *attached_cpu_dev;
+       struct mutex            lock;
+       void __iomem            *base;
+       struct corner           *corner;
+       struct regulator        *vdd_apc;
+       struct clk              *cpu_clk;
+       struct regmap           *tcsr;
+       bool                    loop_disabled;
+       u32                     gcnt;
+       unsigned long           flags;
+
+       struct fuse_corner      *fuse_corners;
+       struct corner           *corners;
+
+       const struct cpr_desc *desc;
+       const struct acc_desc *acc_desc;
+       const struct cpr_fuse *cpr_fuses;
+
+       struct dentry *debugfs;
+};
+
+static bool cpr_is_allowed(struct cpr_drv *drv)
+{
+       return !drv->loop_disabled;
+}
+
+static void cpr_write(struct cpr_drv *drv, u32 offset, u32 value)
+{
+       writel_relaxed(value, drv->base + offset);
+}
+
+static u32 cpr_read(struct cpr_drv *drv, u32 offset)
+{
+       return readl_relaxed(drv->base + offset);
+}
+
+static void
+cpr_masked_write(struct cpr_drv *drv, u32 offset, u32 mask, u32 value)
+{
+       u32 val;
+
+       val = readl_relaxed(drv->base + offset);
+       val &= ~mask;
+       val |= value & mask;
+       writel_relaxed(val, drv->base + offset);
+}
+
+static void cpr_irq_clr(struct cpr_drv *drv)
+{
+       cpr_write(drv, REG_RBIF_IRQ_CLEAR, CPR_INT_ALL);
+}
+
+static void cpr_irq_clr_nack(struct cpr_drv *drv)
+{
+       cpr_irq_clr(drv);
+       cpr_write(drv, REG_RBIF_CONT_NACK_CMD, 1);
+}
+
+static void cpr_irq_clr_ack(struct cpr_drv *drv)
+{
+       cpr_irq_clr(drv);
+       cpr_write(drv, REG_RBIF_CONT_ACK_CMD, 1);
+}
+
+static void cpr_irq_set(struct cpr_drv *drv, u32 int_bits)
+{
+       cpr_write(drv, REG_RBIF_IRQ_EN(0), int_bits);
+}
+
+static void cpr_ctl_modify(struct cpr_drv *drv, u32 mask, u32 value)
+{
+       cpr_masked_write(drv, REG_RBCPR_CTL, mask, value);
+}
+
+static void cpr_ctl_enable(struct cpr_drv *drv, struct corner *corner)
+{
+       u32 val, mask;
+       const struct cpr_desc *desc = drv->desc;
+
+       /* Program Consecutive Up & Down */
+       val = desc->timer_cons_down << RBIF_TIMER_ADJ_CONS_DOWN_SHIFT;
+       val |= desc->timer_cons_up << RBIF_TIMER_ADJ_CONS_UP_SHIFT;
+       mask = RBIF_TIMER_ADJ_CONS_UP_MASK | RBIF_TIMER_ADJ_CONS_DOWN_MASK;
+       cpr_masked_write(drv, REG_RBIF_TIMER_ADJUST, mask, val);
+       cpr_masked_write(drv, REG_RBCPR_CTL,
+                        RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN |
+                        RBCPR_CTL_SW_AUTO_CONT_ACK_EN,
+                        corner->save_ctl);
+       cpr_irq_set(drv, corner->save_irq);
+
+       if (cpr_is_allowed(drv) && corner->max_uV > corner->min_uV)
+               val = RBCPR_CTL_LOOP_EN;
+       else
+               val = 0;
+       cpr_ctl_modify(drv, RBCPR_CTL_LOOP_EN, val);
+}
+
+static void cpr_ctl_disable(struct cpr_drv *drv)
+{
+       cpr_irq_set(drv, 0);
+       cpr_ctl_modify(drv, RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN |
+                      RBCPR_CTL_SW_AUTO_CONT_ACK_EN, 0);
+       cpr_masked_write(drv, REG_RBIF_TIMER_ADJUST,
+                        RBIF_TIMER_ADJ_CONS_UP_MASK |
+                        RBIF_TIMER_ADJ_CONS_DOWN_MASK, 0);
+       cpr_irq_clr(drv);
+       cpr_write(drv, REG_RBIF_CONT_ACK_CMD, 1);
+       cpr_write(drv, REG_RBIF_CONT_NACK_CMD, 1);
+       cpr_ctl_modify(drv, RBCPR_CTL_LOOP_EN, 0);
+}
+
+static bool cpr_ctl_is_enabled(struct cpr_drv *drv)
+{
+       u32 reg_val;
+
+       reg_val = cpr_read(drv, REG_RBCPR_CTL);
+       return reg_val & RBCPR_CTL_LOOP_EN;
+}
+
+static bool cpr_ctl_is_busy(struct cpr_drv *drv)
+{
+       u32 reg_val;
+
+       reg_val = cpr_read(drv, REG_RBCPR_RESULT_0);
+       return reg_val & RBCPR_RESULT0_BUSY_MASK;
+}
+
+static void cpr_corner_save(struct cpr_drv *drv, struct corner *corner)
+{
+       corner->save_ctl = cpr_read(drv, REG_RBCPR_CTL);
+       corner->save_irq = cpr_read(drv, REG_RBIF_IRQ_EN(0));
+}
+
+static void cpr_corner_restore(struct cpr_drv *drv, struct corner *corner)
+{
+       u32 gcnt, ctl, irq, ro_sel, step_quot;
+       struct fuse_corner *fuse = corner->fuse_corner;
+       const struct cpr_desc *desc = drv->desc;
+       int i;
+
+       ro_sel = fuse->ring_osc_idx;
+       gcnt = drv->gcnt;
+       gcnt |= fuse->quot - corner->quot_adjust;
+
+       /* Program the step quotient and idle clocks */
+       step_quot = desc->idle_clocks << RBCPR_STEP_QUOT_IDLE_CLK_SHIFT;
+       step_quot |= fuse->step_quot & RBCPR_STEP_QUOT_STEPQUOT_MASK;
+       cpr_write(drv, REG_RBCPR_STEP_QUOT, step_quot);
+
+       /* Clear the target quotient value and gate count of all ROs */
+       for (i = 0; i < CPR_NUM_RING_OSC; i++)
+               cpr_write(drv, REG_RBCPR_GCNT_TARGET(i), 0);
+
+       cpr_write(drv, REG_RBCPR_GCNT_TARGET(ro_sel), gcnt);
+       ctl = corner->save_ctl;
+       cpr_write(drv, REG_RBCPR_CTL, ctl);
+       irq = corner->save_irq;
+       cpr_irq_set(drv, irq);
+       dev_dbg(drv->dev, "gcnt = %#08x, ctl = %#08x, irq = %#08x\n", gcnt,
+               ctl, irq);
+}
+
+static void cpr_set_acc(struct regmap *tcsr, struct fuse_corner *f,
+                       struct fuse_corner *end)
+{
+       if (f == end)
+               return;
+
+       if (f < end) {
+               for (f += 1; f <= end; f++)
+                       regmap_multi_reg_write(tcsr, f->accs, f->num_accs);
+       } else {
+               for (f -= 1; f >= end; f--)
+                       regmap_multi_reg_write(tcsr, f->accs, f->num_accs);
+       }
+}
+
+static int cpr_pre_voltage(struct cpr_drv *drv,
+                          struct fuse_corner *fuse_corner,
+                          enum voltage_change_dir dir)
+{
+       struct fuse_corner *prev_fuse_corner = drv->corner->fuse_corner;
+
+       if (drv->tcsr && dir == DOWN)
+               cpr_set_acc(drv->tcsr, prev_fuse_corner, fuse_corner);
+
+       return 0;
+}
+
+static int cpr_post_voltage(struct cpr_drv *drv,
+                           struct fuse_corner *fuse_corner,
+                           enum voltage_change_dir dir)
+{
+       struct fuse_corner *prev_fuse_corner = drv->corner->fuse_corner;
+
+       if (drv->tcsr && dir == UP)
+               cpr_set_acc(drv->tcsr, prev_fuse_corner, fuse_corner);
+
+       return 0;
+}
+
+static int cpr_scale_voltage(struct cpr_drv *drv, struct corner *corner,
+                            int new_uV, enum voltage_change_dir dir)
+{
+       int ret;
+       struct fuse_corner *fuse_corner = corner->fuse_corner;
+
+       ret = cpr_pre_voltage(drv, fuse_corner, dir);
+       if (ret)
+               return ret;
+
+       ret = regulator_set_voltage(drv->vdd_apc, new_uV, new_uV);
+       if (ret) {
+               dev_err_ratelimited(drv->dev, "failed to set apc voltage %d\n",
+                                   new_uV);
+               return ret;
+       }
+
+       ret = cpr_post_voltage(drv, fuse_corner, dir);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static unsigned int cpr_get_cur_perf_state(struct cpr_drv *drv)
+{
+       return drv->corner ? drv->corner - drv->corners + 1 : 0;
+}
+
+static int cpr_scale(struct cpr_drv *drv, enum voltage_change_dir dir)
+{
+       u32 val, error_steps, reg_mask;
+       int last_uV, new_uV, step_uV, ret;
+       struct corner *corner;
+       const struct cpr_desc *desc = drv->desc;
+
+       if (dir != UP && dir != DOWN)
+               return 0;
+
+       step_uV = regulator_get_linear_step(drv->vdd_apc);
+       if (!step_uV)
+               return -EINVAL;
+
+       corner = drv->corner;
+
+       val = cpr_read(drv, REG_RBCPR_RESULT_0);
+
+       error_steps = val >> RBCPR_RESULT0_ERROR_STEPS_SHIFT;
+       error_steps &= RBCPR_RESULT0_ERROR_STEPS_MASK;
+       last_uV = corner->last_uV;
+
+       if (dir == UP) {
+               if (desc->clamp_timer_interval &&
+                   error_steps < desc->up_threshold) {
+                       /*
+                        * Handle the case where another measurement started
+                        * after the interrupt was triggered due to a core
+                        * exiting from power collapse.
+                        */
+                       error_steps = max(desc->up_threshold,
+                                         desc->vdd_apc_step_up_limit);
+               }
+
+               if (last_uV >= corner->max_uV) {
+                       cpr_irq_clr_nack(drv);
+
+                       /* Maximize the UP threshold */
+                       reg_mask = RBCPR_CTL_UP_THRESHOLD_MASK;
+                       reg_mask <<= RBCPR_CTL_UP_THRESHOLD_SHIFT;
+                       val = reg_mask;
+                       cpr_ctl_modify(drv, reg_mask, val);
+
+                       /* Disable UP interrupt */
+                       cpr_irq_set(drv, CPR_INT_DEFAULT & ~CPR_INT_UP);
+
+                       return 0;
+               }
+
+               if (error_steps > desc->vdd_apc_step_up_limit)
+                       error_steps = desc->vdd_apc_step_up_limit;
+
+               /* Calculate new voltage */
+               new_uV = last_uV + error_steps * step_uV;
+               new_uV = min(new_uV, corner->max_uV);
+
+               dev_dbg(drv->dev,
+                       "UP: -> new_uV: %d last_uV: %d perf state: %u\n",
+                       new_uV, last_uV, cpr_get_cur_perf_state(drv));
+       } else {
+               if (desc->clamp_timer_interval &&
+                   error_steps < desc->down_threshold) {
+                       /*
+                        * Handle the case where another measurement started
+                        * after the interrupt was triggered due to a core
+                        * exiting from power collapse.
+                        */
+                       error_steps = max(desc->down_threshold,
+                                         desc->vdd_apc_step_down_limit);
+               }
+
+               if (last_uV <= corner->min_uV) {
+                       cpr_irq_clr_nack(drv);
+
+                       /* Enable auto nack down */
+                       reg_mask = RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
+                       val = RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
+
+                       cpr_ctl_modify(drv, reg_mask, val);
+
+                       /* Disable DOWN interrupt */
+                       cpr_irq_set(drv, CPR_INT_DEFAULT & ~CPR_INT_DOWN);
+
+                       return 0;
+               }
+
+               if (error_steps > desc->vdd_apc_step_down_limit)
+                       error_steps = desc->vdd_apc_step_down_limit;
+
+               /* Calculate new voltage */
+               new_uV = last_uV - error_steps * step_uV;
+               new_uV = max(new_uV, corner->min_uV);
+
+               dev_dbg(drv->dev,
+                       "DOWN: -> new_uV: %d last_uV: %d perf state: %u\n",
+                       new_uV, last_uV, cpr_get_cur_perf_state(drv));
+       }
+
+       ret = cpr_scale_voltage(drv, corner, new_uV, dir);
+       if (ret) {
+               cpr_irq_clr_nack(drv);
+               return ret;
+       }
+       drv->corner->last_uV = new_uV;
+
+       if (dir == UP) {
+               /* Disable auto nack down */
+               reg_mask = RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
+               val = 0;
+       } else {
+               /* Restore default threshold for UP */
+               reg_mask = RBCPR_CTL_UP_THRESHOLD_MASK;
+               reg_mask <<= RBCPR_CTL_UP_THRESHOLD_SHIFT;
+               val = desc->up_threshold;
+               val <<= RBCPR_CTL_UP_THRESHOLD_SHIFT;
+       }
+
+       cpr_ctl_modify(drv, reg_mask, val);
+
+       /* Re-enable default interrupts */
+       cpr_irq_set(drv, CPR_INT_DEFAULT);
+
+       /* Ack */
+       cpr_irq_clr_ack(drv);
+
+       return 0;
+}
+
+static irqreturn_t cpr_irq_handler(int irq, void *dev)
+{
+       struct cpr_drv *drv = dev;
+       const struct cpr_desc *desc = drv->desc;
+       irqreturn_t ret = IRQ_HANDLED;
+       u32 val;
+
+       mutex_lock(&drv->lock);
+
+       val = cpr_read(drv, REG_RBIF_IRQ_STATUS);
+       if (drv->flags & FLAGS_IGNORE_1ST_IRQ_STATUS)
+               val = cpr_read(drv, REG_RBIF_IRQ_STATUS);
+
+       dev_dbg(drv->dev, "IRQ_STATUS = %#02x\n", val);
+
+       if (!cpr_ctl_is_enabled(drv)) {
+               dev_dbg(drv->dev, "CPR is disabled\n");
+               ret = IRQ_NONE;
+       } else if (cpr_ctl_is_busy(drv) && !desc->clamp_timer_interval) {
+               dev_dbg(drv->dev, "CPR measurement is not ready\n");
+       } else if (!cpr_is_allowed(drv)) {
+               val = cpr_read(drv, REG_RBCPR_CTL);
+               dev_err_ratelimited(drv->dev,
+                                   "Interrupt broken? RBCPR_CTL = %#02x\n",
+                                   val);
+               ret = IRQ_NONE;
+       } else {
+               /*
+                * Following sequence of handling is as per each IRQ's
+                * priority
+                */
+               if (val & CPR_INT_UP) {
+                       cpr_scale(drv, UP);
+               } else if (val & CPR_INT_DOWN) {
+                       cpr_scale(drv, DOWN);
+               } else if (val & CPR_INT_MIN) {
+                       cpr_irq_clr_nack(drv);
+               } else if (val & CPR_INT_MAX) {
+                       cpr_irq_clr_nack(drv);
+               } else if (val & CPR_INT_MID) {
+                       /* RBCPR_CTL_SW_AUTO_CONT_ACK_EN is enabled */
+                       dev_dbg(drv->dev, "IRQ occurred for Mid Flag\n");
+               } else {
+                       dev_dbg(drv->dev,
+                               "IRQ occurred for unknown flag (%#08x)\n", val);
+               }
+
+               /* Save register values for the corner */
+               cpr_corner_save(drv, drv->corner);
+       }
+
+       mutex_unlock(&drv->lock);
+
+       return ret;
+}
+
+static int cpr_enable(struct cpr_drv *drv)
+{
+       int ret;
+
+       ret = regulator_enable(drv->vdd_apc);
+       if (ret)
+               return ret;
+
+       mutex_lock(&drv->lock);
+
+       if (cpr_is_allowed(drv) && drv->corner) {
+               cpr_irq_clr(drv);
+               cpr_corner_restore(drv, drv->corner);
+               cpr_ctl_enable(drv, drv->corner);
+       }
+
+       mutex_unlock(&drv->lock);
+
+       return 0;
+}
+
+static int cpr_disable(struct cpr_drv *drv)
+{
+       mutex_lock(&drv->lock);
+
+       if (cpr_is_allowed(drv)) {
+               cpr_ctl_disable(drv);
+               cpr_irq_clr(drv);
+       }
+
+       mutex_unlock(&drv->lock);
+
+       return regulator_disable(drv->vdd_apc);
+}
+
+static int cpr_config(struct cpr_drv *drv)
+{
+       int i;
+       u32 val, gcnt;
+       struct corner *corner;
+       const struct cpr_desc *desc = drv->desc;
+
+       /* Disable interrupt and CPR */
+       cpr_write(drv, REG_RBIF_IRQ_EN(0), 0);
+       cpr_write(drv, REG_RBCPR_CTL, 0);
+
+       /* Program the default HW ceiling, floor and vlevel */
+       val = (RBIF_LIMIT_CEILING_DEFAULT & RBIF_LIMIT_CEILING_MASK)
+               << RBIF_LIMIT_CEILING_SHIFT;
+       val |= RBIF_LIMIT_FLOOR_DEFAULT & RBIF_LIMIT_FLOOR_MASK;
+       cpr_write(drv, REG_RBIF_LIMIT, val);
+       cpr_write(drv, REG_RBIF_SW_VLEVEL, RBIF_SW_VLEVEL_DEFAULT);
+
+       /*
+        * Clear the target quotient value and gate count of all
+        * ring oscillators
+        */
+       for (i = 0; i < CPR_NUM_RING_OSC; i++)
+               cpr_write(drv, REG_RBCPR_GCNT_TARGET(i), 0);
+
+       /* Init and save gcnt */
+       gcnt = (drv->ref_clk_khz * desc->gcnt_us) / 1000;
+       gcnt = gcnt & RBCPR_GCNT_TARGET_GCNT_MASK;
+       gcnt <<= RBCPR_GCNT_TARGET_GCNT_SHIFT;
+       drv->gcnt = gcnt;
+
+       /* Program the delay count for the timer */
+       val = (drv->ref_clk_khz * desc->timer_delay_us) / 1000;
+       cpr_write(drv, REG_RBCPR_TIMER_INTERVAL, val);
+       dev_dbg(drv->dev, "Timer count: %#0x (for %d us)\n", val,
+               desc->timer_delay_us);
+
+       /* Program Consecutive Up & Down */
+       val = desc->timer_cons_down << RBIF_TIMER_ADJ_CONS_DOWN_SHIFT;
+       val |= desc->timer_cons_up << RBIF_TIMER_ADJ_CONS_UP_SHIFT;
+       val |= desc->clamp_timer_interval << RBIF_TIMER_ADJ_CLAMP_INT_SHIFT;
+       cpr_write(drv, REG_RBIF_TIMER_ADJUST, val);
+
+       /* Program the control register */
+       val = desc->up_threshold << RBCPR_CTL_UP_THRESHOLD_SHIFT;
+       val |= desc->down_threshold << RBCPR_CTL_DN_THRESHOLD_SHIFT;
+       val |= RBCPR_CTL_TIMER_EN | RBCPR_CTL_COUNT_MODE;
+       val |= RBCPR_CTL_SW_AUTO_CONT_ACK_EN;
+       cpr_write(drv, REG_RBCPR_CTL, val);
+
+       for (i = 0; i < drv->num_corners; i++) {
+               corner = &drv->corners[i];
+               corner->save_ctl = val;
+               corner->save_irq = CPR_INT_DEFAULT;
+       }
+
+       cpr_irq_set(drv, CPR_INT_DEFAULT);
+
+       val = cpr_read(drv, REG_RBCPR_VERSION);
+       if (val <= RBCPR_VER_2)
+               drv->flags |= FLAGS_IGNORE_1ST_IRQ_STATUS;
+
+       return 0;
+}
+
+static int cpr_set_performance_state(struct generic_pm_domain *domain,
+                                    unsigned int state)
+{
+       struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd);
+       struct corner *corner, *end;
+       enum voltage_change_dir dir;
+       int ret = 0, new_uV;
+
+       mutex_lock(&drv->lock);
+
+       dev_dbg(drv->dev, "%s: setting perf state: %u (prev state: %u)\n",
+               __func__, state, cpr_get_cur_perf_state(drv));
+
+       /*
+        * Determine new corner we're going to.
+        * Remove one since lowest performance state is 1.
+        */
+       corner = drv->corners + state - 1;
+       end = &drv->corners[drv->num_corners - 1];
+       if (corner > end || corner < drv->corners) {
+               ret = -EINVAL;
+               goto unlock;
+       }
+
+       /* Determine direction */
+       if (drv->corner > corner)
+               dir = DOWN;
+       else if (drv->corner < corner)
+               dir = UP;
+       else
+               dir = NO_CHANGE;
+
+       if (cpr_is_allowed(drv))
+               new_uV = corner->last_uV;
+       else
+               new_uV = corner->uV;
+
+       if (cpr_is_allowed(drv))
+               cpr_ctl_disable(drv);
+
+       ret = cpr_scale_voltage(drv, corner, new_uV, dir);
+       if (ret)
+               goto unlock;
+
+       if (cpr_is_allowed(drv)) {
+               cpr_irq_clr(drv);
+               if (drv->corner != corner)
+                       cpr_corner_restore(drv, corner);
+               cpr_ctl_enable(drv, corner);
+       }
+
+       drv->corner = corner;
+
+unlock:
+       mutex_unlock(&drv->lock);
+
+       return ret;
+}
+
+static int
+cpr_populate_ring_osc_idx(struct cpr_drv *drv)
+{
+       struct fuse_corner *fuse = drv->fuse_corners;
+       struct fuse_corner *end = fuse + drv->desc->num_fuse_corners;
+       const struct cpr_fuse *fuses = drv->cpr_fuses;
+       u32 data;
+       int ret;
+
+       for (; fuse < end; fuse++, fuses++) {
+               ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->ring_osc, &data);
+               if (ret)
+                       return ret;
+               fuse->ring_osc_idx = data;
+       }
+
+       return 0;
+}
+
+static int cpr_read_fuse_uV(const struct cpr_desc *desc,
+                           const struct fuse_corner_data *fdata,
+                           const char *init_v_efuse,
+                           int step_volt,
+                           struct cpr_drv *drv)
+{
+       int step_size_uV, steps, uV;
+       u32 bits = 0;
+       int ret;
+
+       ret = nvmem_cell_read_variable_le_u32(drv->dev, init_v_efuse, &bits);
+       if (ret)
+               return ret;
+
+       steps = bits & ~BIT(desc->cpr_fuses.init_voltage_width - 1);
+       /* Not two's complement.. instead highest bit is sign bit */
+       if (bits & BIT(desc->cpr_fuses.init_voltage_width - 1))
+               steps = -steps;
+
+       step_size_uV = desc->cpr_fuses.init_voltage_step;
+
+       uV = fdata->ref_uV + steps * step_size_uV;
+       return DIV_ROUND_UP(uV, step_volt) * step_volt;
+}
+
+static int cpr_fuse_corner_init(struct cpr_drv *drv)
+{
+       const struct cpr_desc *desc = drv->desc;
+       const struct cpr_fuse *fuses = drv->cpr_fuses;
+       const struct acc_desc *acc_desc = drv->acc_desc;
+       int i;
+       unsigned int step_volt;
+       struct fuse_corner_data *fdata;
+       struct fuse_corner *fuse, *end;
+       int uV;
+       const struct reg_sequence *accs;
+       int ret;
+
+       accs = acc_desc->settings;
+
+       step_volt = regulator_get_linear_step(drv->vdd_apc);
+       if (!step_volt)
+               return -EINVAL;
+
+       /* Populate fuse_corner members */
+       fuse = drv->fuse_corners;
+       end = &fuse[desc->num_fuse_corners - 1];
+       fdata = desc->cpr_fuses.fuse_corner_data;
+
+       for (i = 0; fuse <= end; fuse++, fuses++, i++, fdata++) {
+               /*
+                * Update SoC voltages: platforms might choose a different
+                * regulators than the one used to characterize the algorithms
+                * (ie, init_voltage_step).
+                */
+               fdata->min_uV = roundup(fdata->min_uV, step_volt);
+               fdata->max_uV = roundup(fdata->max_uV, step_volt);
+
+               /* Populate uV */
+               uV = cpr_read_fuse_uV(desc, fdata, fuses->init_voltage,
+                                     step_volt, drv);
+               if (uV < 0)
+                       return uV;
+
+               fuse->min_uV = fdata->min_uV;
+               fuse->max_uV = fdata->max_uV;
+               fuse->uV = clamp(uV, fuse->min_uV, fuse->max_uV);
+
+               if (fuse == end) {
+                       /*
+                        * Allow the highest fuse corner's PVS voltage to
+                        * define the ceiling voltage for that corner in order
+                        * to support SoC's in which variable ceiling values
+                        * are required.
+                        */
+                       end->max_uV = max(end->max_uV, end->uV);
+               }
+
+               /* Populate target quotient by scaling */
+               ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->quotient, &fuse->quot);
+               if (ret)
+                       return ret;
+
+               fuse->quot *= fdata->quot_scale;
+               fuse->quot += fdata->quot_offset;
+               fuse->quot += fdata->quot_adjust;
+               fuse->step_quot = desc->step_quot[fuse->ring_osc_idx];
+
+               /* Populate acc settings */
+               fuse->accs = accs;
+               fuse->num_accs = acc_desc->num_regs_per_fuse;
+               accs += acc_desc->num_regs_per_fuse;
+       }
+
+       /*
+        * Restrict all fuse corner PVS voltages based upon per corner
+        * ceiling and floor voltages.
+        */
+       for (fuse = drv->fuse_corners, i = 0; fuse <= end; fuse++, i++) {
+               if (fuse->uV > fuse->max_uV)
+                       fuse->uV = fuse->max_uV;
+               else if (fuse->uV < fuse->min_uV)
+                       fuse->uV = fuse->min_uV;
+
+               ret = regulator_is_supported_voltage(drv->vdd_apc,
+                                                    fuse->min_uV,
+                                                    fuse->min_uV);
+               if (!ret) {
+                       dev_err(drv->dev,
+                               "min uV: %d (fuse corner: %d) not supported by regulator\n",
+                               fuse->min_uV, i);
+                       return -EINVAL;
+               }
+
+               ret = regulator_is_supported_voltage(drv->vdd_apc,
+                                                    fuse->max_uV,
+                                                    fuse->max_uV);
+               if (!ret) {
+                       dev_err(drv->dev,
+                               "max uV: %d (fuse corner: %d) not supported by regulator\n",
+                               fuse->max_uV, i);
+                       return -EINVAL;
+               }
+
+               dev_dbg(drv->dev,
+                       "fuse corner %d: [%d %d %d] RO%hhu quot %d squot %d\n",
+                       i, fuse->min_uV, fuse->uV, fuse->max_uV,
+                       fuse->ring_osc_idx, fuse->quot, fuse->step_quot);
+       }
+
+       return 0;
+}
+
+static int cpr_calculate_scaling(const char *quot_offset,
+                                struct cpr_drv *drv,
+                                const struct fuse_corner_data *fdata,
+                                const struct corner *corner)
+{
+       u32 quot_diff = 0;
+       unsigned long freq_diff;
+       int scaling;
+       const struct fuse_corner *fuse, *prev_fuse;
+       int ret;
+
+       fuse = corner->fuse_corner;
+       prev_fuse = fuse - 1;
+
+       if (quot_offset) {
+               ret = nvmem_cell_read_variable_le_u32(drv->dev, quot_offset, &quot_diff);
+               if (ret)
+                       return ret;
+
+               quot_diff *= fdata->quot_offset_scale;
+               quot_diff += fdata->quot_offset_adjust;
+       } else {
+               quot_diff = fuse->quot - prev_fuse->quot;
+       }
+
+       freq_diff = fuse->max_freq - prev_fuse->max_freq;
+       freq_diff /= 1000000; /* Convert to MHz */
+       scaling = 1000 * quot_diff / freq_diff;
+       return min(scaling, fdata->max_quot_scale);
+}
+
+static int cpr_interpolate(const struct corner *corner, int step_volt,
+                          const struct fuse_corner_data *fdata)
+{
+       unsigned long f_high, f_low, f_diff;
+       int uV_high, uV_low, uV;
+       u64 temp, temp_limit;
+       const struct fuse_corner *fuse, *prev_fuse;
+
+       fuse = corner->fuse_corner;
+       prev_fuse = fuse - 1;
+
+       f_high = fuse->max_freq;
+       f_low = prev_fuse->max_freq;
+       uV_high = fuse->uV;
+       uV_low = prev_fuse->uV;
+       f_diff = fuse->max_freq - corner->freq;
+
+       /*
+        * Don't interpolate in the wrong direction. This could happen
+        * if the adjusted fuse voltage overlaps with the previous fuse's
+        * adjusted voltage.
+        */
+       if (f_high <= f_low || uV_high <= uV_low || f_high <= corner->freq)
+               return corner->uV;
+
+       temp = f_diff * (uV_high - uV_low);
+       temp = div64_ul(temp, f_high - f_low);
+
+       /*
+        * max_volt_scale has units of uV/MHz while freq values
+        * have units of Hz.  Divide by 1000000 to convert to.
+        */
+       temp_limit = f_diff * fdata->max_volt_scale;
+       do_div(temp_limit, 1000000);
+
+       uV = uV_high - min(temp, temp_limit);
+       return roundup(uV, step_volt);
+}
+
+static unsigned int cpr_get_fuse_corner(struct dev_pm_opp *opp)
+{
+       struct device_node *np;
+       unsigned int fuse_corner = 0;
+
+       np = dev_pm_opp_get_of_node(opp);
+       if (of_property_read_u32(np, "qcom,opp-fuse-level", &fuse_corner))
+               pr_err("%s: missing 'qcom,opp-fuse-level' property\n",
+                      __func__);
+
+       of_node_put(np);
+
+       return fuse_corner;
+}
+
+static unsigned long cpr_get_opp_hz_for_req(struct dev_pm_opp *ref,
+                                           struct device *cpu_dev)
+{
+       u64 rate = 0;
+       struct device_node *ref_np;
+       struct device_node *desc_np;
+       struct device_node *child_np = NULL;
+       struct device_node *child_req_np = NULL;
+
+       desc_np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
+       if (!desc_np)
+               return 0;
+
+       ref_np = dev_pm_opp_get_of_node(ref);
+       if (!ref_np)
+               goto out_ref;
+
+       do {
+               of_node_put(child_req_np);
+               child_np = of_get_next_available_child(desc_np, child_np);
+               child_req_np = of_parse_phandle(child_np, "required-opps", 0);
+       } while (child_np && child_req_np != ref_np);
+
+       if (child_np && child_req_np == ref_np)
+               of_property_read_u64(child_np, "opp-hz", &rate);
+
+       of_node_put(child_req_np);
+       of_node_put(child_np);
+       of_node_put(ref_np);
+out_ref:
+       of_node_put(desc_np);
+
+       return (unsigned long) rate;
+}
+
+static int cpr_corner_init(struct cpr_drv *drv)
+{
+       const struct cpr_desc *desc = drv->desc;
+       const struct cpr_fuse *fuses = drv->cpr_fuses;
+       int i, level, scaling = 0;
+       unsigned int fnum, fc;
+       const char *quot_offset;
+       struct fuse_corner *fuse, *prev_fuse;
+       struct corner *corner, *end;
+       struct corner_data *cdata;
+       const struct fuse_corner_data *fdata;
+       bool apply_scaling;
+       unsigned long freq_diff, freq_diff_mhz;
+       unsigned long freq;
+       int step_volt = regulator_get_linear_step(drv->vdd_apc);
+       struct dev_pm_opp *opp;
+
+       if (!step_volt)
+               return -EINVAL;
+
+       corner = drv->corners;
+       end = &corner[drv->num_corners - 1];
+
+       cdata = devm_kcalloc(drv->dev, drv->num_corners,
+                            sizeof(struct corner_data),
+                            GFP_KERNEL);
+       if (!cdata)
+               return -ENOMEM;
+
+       /*
+        * Store maximum frequency for each fuse corner based on the frequency
+        * plan
+        */
+       for (level = 1; level <= drv->num_corners; level++) {
+               opp = dev_pm_opp_find_level_exact(&drv->pd.dev, level);
+               if (IS_ERR(opp))
+                       return -EINVAL;
+               fc = cpr_get_fuse_corner(opp);
+               if (!fc) {
+                       dev_pm_opp_put(opp);
+                       return -EINVAL;
+               }
+               fnum = fc - 1;
+               freq = cpr_get_opp_hz_for_req(opp, drv->attached_cpu_dev);
+               if (!freq) {
+                       dev_pm_opp_put(opp);
+                       return -EINVAL;
+               }
+               cdata[level - 1].fuse_corner = fnum;
+               cdata[level - 1].freq = freq;
+
+               fuse = &drv->fuse_corners[fnum];
+               dev_dbg(drv->dev, "freq: %lu level: %u fuse level: %u\n",
+                       freq, dev_pm_opp_get_level(opp) - 1, fnum);
+               if (freq > fuse->max_freq)
+                       fuse->max_freq = freq;
+               dev_pm_opp_put(opp);
+       }
+
+       /*
+        * Get the quotient adjustment scaling factor, according to:
+        *
+        * scaling = min(1000 * (QUOT(corner_N) - QUOT(corner_N-1))
+        *              / (freq(corner_N) - freq(corner_N-1)), max_factor)
+        *
+        * QUOT(corner_N):      quotient read from fuse for fuse corner N
+        * QUOT(corner_N-1):    quotient read from fuse for fuse corner (N - 1)
+        * freq(corner_N):      max frequency in MHz supported by fuse corner N
+        * freq(corner_N-1):    max frequency in MHz supported by fuse corner
+        *                       (N - 1)
+        *
+        * Then walk through the corners mapped to each fuse corner
+        * and calculate the quotient adjustment for each one using the
+        * following formula:
+        *
+        * quot_adjust = (freq_max - freq_corner) * scaling / 1000
+        *
+        * freq_max: max frequency in MHz supported by the fuse corner
+        * freq_corner: frequency in MHz corresponding to the corner
+        * scaling: calculated from above equation
+        *
+        *
+        *     +                           +
+        *     |                         v |
+        *   q |           f c           o |           f c
+        *   u |         c               l |         c
+        *   o |       f                 t |       f
+        *   t |     c                   a |     c
+        *     | c f                     g | c f
+        *     |                         e |
+        *     +---------------            +----------------
+        *       0 1 2 3 4 5 6               0 1 2 3 4 5 6
+        *          corner                      corner
+        *
+        *    c = corner
+        *    f = fuse corner
+        *
+        */
+       for (apply_scaling = false, i = 0; corner <= end; corner++, i++) {
+               fnum = cdata[i].fuse_corner;
+               fdata = &desc->cpr_fuses.fuse_corner_data[fnum];
+               quot_offset = fuses[fnum].quotient_offset;
+               fuse = &drv->fuse_corners[fnum];
+               if (fnum)
+                       prev_fuse = &drv->fuse_corners[fnum - 1];
+               else
+                       prev_fuse = NULL;
+
+               corner->fuse_corner = fuse;
+               corner->freq = cdata[i].freq;
+               corner->uV = fuse->uV;
+
+               if (prev_fuse && cdata[i - 1].freq == prev_fuse->max_freq) {
+                       scaling = cpr_calculate_scaling(quot_offset, drv,
+                                                       fdata, corner);
+                       if (scaling < 0)
+                               return scaling;
+
+                       apply_scaling = true;
+               } else if (corner->freq == fuse->max_freq) {
+                       /* This is a fuse corner; don't scale anything */
+                       apply_scaling = false;
+               }
+
+               if (apply_scaling) {
+                       freq_diff = fuse->max_freq - corner->freq;
+                       freq_diff_mhz = freq_diff / 1000000;
+                       corner->quot_adjust = scaling * freq_diff_mhz / 1000;
+
+                       corner->uV = cpr_interpolate(corner, step_volt, fdata);
+               }
+
+               corner->max_uV = fuse->max_uV;
+               corner->min_uV = fuse->min_uV;
+               corner->uV = clamp(corner->uV, corner->min_uV, corner->max_uV);
+               corner->last_uV = corner->uV;
+
+               /* Reduce the ceiling voltage if needed */
+               if (desc->reduce_to_corner_uV && corner->uV < corner->max_uV)
+                       corner->max_uV = corner->uV;
+               else if (desc->reduce_to_fuse_uV && fuse->uV < corner->max_uV)
+                       corner->max_uV = max(corner->min_uV, fuse->uV);
+
+               dev_dbg(drv->dev, "corner %d: [%d %d %d] quot %d\n", i,
+                       corner->min_uV, corner->uV, corner->max_uV,
+                       fuse->quot - corner->quot_adjust);
+       }
+
+       return 0;
+}
+
+static const struct cpr_fuse *cpr_get_fuses(struct cpr_drv *drv)
+{
+       const struct cpr_desc *desc = drv->desc;
+       struct cpr_fuse *fuses;
+       int i;
+
+       fuses = devm_kcalloc(drv->dev, desc->num_fuse_corners,
+                            sizeof(struct cpr_fuse),
+                            GFP_KERNEL);
+       if (!fuses)
+               return ERR_PTR(-ENOMEM);
+
+       for (i = 0; i < desc->num_fuse_corners; i++) {
+               char tbuf[32];
+
+               snprintf(tbuf, 32, "cpr_ring_osc%d", i + 1);
+               fuses[i].ring_osc = devm_kstrdup(drv->dev, tbuf, GFP_KERNEL);
+               if (!fuses[i].ring_osc)
+                       return ERR_PTR(-ENOMEM);
+
+               snprintf(tbuf, 32, "cpr_init_voltage%d", i + 1);
+               fuses[i].init_voltage = devm_kstrdup(drv->dev, tbuf,
+                                                    GFP_KERNEL);
+               if (!fuses[i].init_voltage)
+                       return ERR_PTR(-ENOMEM);
+
+               snprintf(tbuf, 32, "cpr_quotient%d", i + 1);
+               fuses[i].quotient = devm_kstrdup(drv->dev, tbuf, GFP_KERNEL);
+               if (!fuses[i].quotient)
+                       return ERR_PTR(-ENOMEM);
+
+               snprintf(tbuf, 32, "cpr_quotient_offset%d", i + 1);
+               fuses[i].quotient_offset = devm_kstrdup(drv->dev, tbuf,
+                                                       GFP_KERNEL);
+               if (!fuses[i].quotient_offset)
+                       return ERR_PTR(-ENOMEM);
+       }
+
+       return fuses;
+}
+
+static void cpr_set_loop_allowed(struct cpr_drv *drv)
+{
+       drv->loop_disabled = false;
+}
+
+static int cpr_init_parameters(struct cpr_drv *drv)
+{
+       const struct cpr_desc *desc = drv->desc;
+       struct clk *clk;
+
+       clk = clk_get(drv->dev, "ref");
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       drv->ref_clk_khz = clk_get_rate(clk) / 1000;
+       clk_put(clk);
+
+       if (desc->timer_cons_up > RBIF_TIMER_ADJ_CONS_UP_MASK ||
+           desc->timer_cons_down > RBIF_TIMER_ADJ_CONS_DOWN_MASK ||
+           desc->up_threshold > RBCPR_CTL_UP_THRESHOLD_MASK ||
+           desc->down_threshold > RBCPR_CTL_DN_THRESHOLD_MASK ||
+           desc->idle_clocks > RBCPR_STEP_QUOT_IDLE_CLK_MASK ||
+           desc->clamp_timer_interval > RBIF_TIMER_ADJ_CLAMP_INT_MASK)
+               return -EINVAL;
+
+       dev_dbg(drv->dev, "up threshold = %u, down threshold = %u\n",
+               desc->up_threshold, desc->down_threshold);
+
+       return 0;
+}
+
+static int cpr_find_initial_corner(struct cpr_drv *drv)
+{
+       unsigned long rate;
+       const struct corner *end;
+       struct corner *iter;
+       unsigned int i = 0;
+
+       if (!drv->cpu_clk) {
+               dev_err(drv->dev, "cannot get rate from NULL clk\n");
+               return -EINVAL;
+       }
+
+       end = &drv->corners[drv->num_corners - 1];
+       rate = clk_get_rate(drv->cpu_clk);
+
+       /*
+        * Some bootloaders set a CPU clock frequency that is not defined
+        * in the OPP table. When running at an unlisted frequency,
+        * cpufreq_online() will change to the OPP which has the lowest
+        * frequency, at or above the unlisted frequency.
+        * Since cpufreq_online() always "rounds up" in the case of an
+        * unlisted frequency, this function always "rounds down" in case
+        * of an unlisted frequency. That way, when cpufreq_online()
+        * triggers the first ever call to cpr_set_performance_state(),
+        * it will correctly determine the direction as UP.
+        */
+       for (iter = drv->corners; iter <= end; iter++) {
+               if (iter->freq > rate)
+                       break;
+               i++;
+               if (iter->freq == rate) {
+                       drv->corner = iter;
+                       break;
+               }
+               if (iter->freq < rate)
+                       drv->corner = iter;
+       }
+
+       if (!drv->corner) {
+               dev_err(drv->dev, "boot up corner not found\n");
+               return -EINVAL;
+       }
+
+       dev_dbg(drv->dev, "boot up perf state: %u\n", i);
+
+       return 0;
+}
+
+static const struct cpr_desc qcs404_cpr_desc = {
+       .num_fuse_corners = 3,
+       .min_diff_quot = CPR_FUSE_MIN_QUOT_DIFF,
+       .step_quot = (int []){ 25, 25, 25, },
+       .timer_delay_us = 5000,
+       .timer_cons_up = 0,
+       .timer_cons_down = 2,
+       .up_threshold = 1,
+       .down_threshold = 3,
+       .idle_clocks = 15,
+       .gcnt_us = 1,
+       .vdd_apc_step_up_limit = 1,
+       .vdd_apc_step_down_limit = 1,
+       .cpr_fuses = {
+               .init_voltage_step = 8000,
+               .init_voltage_width = 6,
+               .fuse_corner_data = (struct fuse_corner_data[]){
+                       /* fuse corner 0 */
+                       {
+                               .ref_uV = 1224000,
+                               .max_uV = 1224000,
+                               .min_uV = 1048000,
+                               .max_volt_scale = 0,
+                               .max_quot_scale = 0,
+                               .quot_offset = 0,
+                               .quot_scale = 1,
+                               .quot_adjust = 0,
+                               .quot_offset_scale = 5,
+                               .quot_offset_adjust = 0,
+                       },
+                       /* fuse corner 1 */
+                       {
+                               .ref_uV = 1288000,
+                               .max_uV = 1288000,
+                               .min_uV = 1048000,
+                               .max_volt_scale = 2000,
+                               .max_quot_scale = 1400,
+                               .quot_offset = 0,
+                               .quot_scale = 1,
+                               .quot_adjust = -20,
+                               .quot_offset_scale = 5,
+                               .quot_offset_adjust = 0,
+                       },
+                       /* fuse corner 2 */
+                       {
+                               .ref_uV = 1352000,
+                               .max_uV = 1384000,
+                               .min_uV = 1088000,
+                               .max_volt_scale = 2000,
+                               .max_quot_scale = 1400,
+                               .quot_offset = 0,
+                               .quot_scale = 1,
+                               .quot_adjust = 0,
+                               .quot_offset_scale = 5,
+                               .quot_offset_adjust = 0,
+                       },
+               },
+       },
+};
+
+static const struct acc_desc qcs404_acc_desc = {
+       .settings = (struct reg_sequence[]){
+               { 0xb120, 0x1041040 },
+               { 0xb124, 0x41 },
+               { 0xb120, 0x0 },
+               { 0xb124, 0x0 },
+               { 0xb120, 0x0 },
+               { 0xb124, 0x0 },
+       },
+       .config = (struct reg_sequence[]){
+               { 0xb138, 0xff },
+               { 0xb130, 0x5555 },
+       },
+       .num_regs_per_fuse = 2,
+};
+
+static const struct cpr_acc_desc qcs404_cpr_acc_desc = {
+       .cpr_desc = &qcs404_cpr_desc,
+       .acc_desc = &qcs404_acc_desc,
+};
+
+static unsigned int cpr_get_performance_state(struct generic_pm_domain *genpd,
+                                             struct dev_pm_opp *opp)
+{
+       return dev_pm_opp_get_level(opp);
+}
+
+static int cpr_power_off(struct generic_pm_domain *domain)
+{
+       struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd);
+
+       return cpr_disable(drv);
+}
+
+static int cpr_power_on(struct generic_pm_domain *domain)
+{
+       struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd);
+
+       return cpr_enable(drv);
+}
+
+static int cpr_pd_attach_dev(struct generic_pm_domain *domain,
+                            struct device *dev)
+{
+       struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd);
+       const struct acc_desc *acc_desc = drv->acc_desc;
+       int ret = 0;
+
+       mutex_lock(&drv->lock);
+
+       dev_dbg(drv->dev, "attach callback for: %s\n", dev_name(dev));
+
+       /*
+        * This driver only supports scaling voltage for a CPU cluster
+        * where all CPUs in the cluster share a single regulator.
+        * Therefore, save the struct device pointer only for the first
+        * CPU device that gets attached. There is no need to do any
+        * additional initialization when further CPUs get attached.
+        */
+       if (drv->attached_cpu_dev)
+               goto unlock;
+
+       /*
+        * cpr_scale_voltage() requires the direction (if we are changing
+        * to a higher or lower OPP). The first time
+        * cpr_set_performance_state() is called, there is no previous
+        * performance state defined. Therefore, we call
+        * cpr_find_initial_corner() that gets the CPU clock frequency
+        * set by the bootloader, so that we can determine the direction
+        * the first time cpr_set_performance_state() is called.
+        */
+       drv->cpu_clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(drv->cpu_clk)) {
+               ret = PTR_ERR(drv->cpu_clk);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(drv->dev, "could not get cpu clk: %d\n", ret);
+               goto unlock;
+       }
+       drv->attached_cpu_dev = dev;
+
+       dev_dbg(drv->dev, "using cpu clk from: %s\n",
+               dev_name(drv->attached_cpu_dev));
+
+       /*
+        * Everything related to (virtual) corners has to be initialized
+        * here, when attaching to the power domain, since we need to know
+        * the maximum frequency for each fuse corner, and this is only
+        * available after the cpufreq driver has attached to us.
+        * The reason for this is that we need to know the highest
+        * frequency associated with each fuse corner.
+        */
+       ret = dev_pm_opp_get_opp_count(&drv->pd.dev);
+       if (ret < 0) {
+               dev_err(drv->dev, "could not get OPP count\n");
+               goto unlock;
+       }
+       drv->num_corners = ret;
+
+       if (drv->num_corners < 2) {
+               dev_err(drv->dev, "need at least 2 OPPs to use CPR\n");
+               ret = -EINVAL;
+               goto unlock;
+       }
+
+       drv->corners = devm_kcalloc(drv->dev, drv->num_corners,
+                                   sizeof(*drv->corners),
+                                   GFP_KERNEL);
+       if (!drv->corners) {
+               ret = -ENOMEM;
+               goto unlock;
+       }
+
+       ret = cpr_corner_init(drv);
+       if (ret)
+               goto unlock;
+
+       cpr_set_loop_allowed(drv);
+
+       ret = cpr_init_parameters(drv);
+       if (ret)
+               goto unlock;
+
+       /* Configure CPR HW but keep it disabled */
+       ret = cpr_config(drv);
+       if (ret)
+               goto unlock;
+
+       ret = cpr_find_initial_corner(drv);
+       if (ret)
+               goto unlock;
+
+       if (acc_desc->config)
+               regmap_multi_reg_write(drv->tcsr, acc_desc->config,
+                                      acc_desc->num_regs_per_fuse);
+
+       /* Enable ACC if required */
+       if (acc_desc->enable_mask)
+               regmap_update_bits(drv->tcsr, acc_desc->enable_reg,
+                                  acc_desc->enable_mask,
+                                  acc_desc->enable_mask);
+
+       dev_info(drv->dev, "driver initialized with %u OPPs\n",
+                drv->num_corners);
+
+unlock:
+       mutex_unlock(&drv->lock);
+
+       return ret;
+}
+
+static int cpr_debug_info_show(struct seq_file *s, void *unused)
+{
+       u32 gcnt, ro_sel, ctl, irq_status, reg, error_steps;
+       u32 step_dn, step_up, error, error_lt0, busy;
+       struct cpr_drv *drv = s->private;
+       struct fuse_corner *fuse_corner;
+       struct corner *corner;
+
+       corner = drv->corner;
+       fuse_corner = corner->fuse_corner;
+
+       seq_printf(s, "corner, current_volt = %d uV\n",
+                      corner->last_uV);
+
+       ro_sel = fuse_corner->ring_osc_idx;
+       gcnt = cpr_read(drv, REG_RBCPR_GCNT_TARGET(ro_sel));
+       seq_printf(s, "rbcpr_gcnt_target (%u) = %#02X\n", ro_sel, gcnt);
+
+       ctl = cpr_read(drv, REG_RBCPR_CTL);
+       seq_printf(s, "rbcpr_ctl = %#02X\n", ctl);
+
+       irq_status = cpr_read(drv, REG_RBIF_IRQ_STATUS);
+       seq_printf(s, "rbcpr_irq_status = %#02X\n", irq_status);
+
+       reg = cpr_read(drv, REG_RBCPR_RESULT_0);
+       seq_printf(s, "rbcpr_result_0 = %#02X\n", reg);
+
+       step_dn = reg & 0x01;
+       step_up = (reg >> RBCPR_RESULT0_STEP_UP_SHIFT) & 0x01;
+       seq_printf(s, "  [step_dn = %u", step_dn);
+
+       seq_printf(s, ", step_up = %u", step_up);
+
+       error_steps = (reg >> RBCPR_RESULT0_ERROR_STEPS_SHIFT)
+                               & RBCPR_RESULT0_ERROR_STEPS_MASK;
+       seq_printf(s, ", error_steps = %u", error_steps);
+
+       error = (reg >> RBCPR_RESULT0_ERROR_SHIFT) & RBCPR_RESULT0_ERROR_MASK;
+       seq_printf(s, ", error = %u", error);
+
+       error_lt0 = (reg >> RBCPR_RESULT0_ERROR_LT0_SHIFT) & 0x01;
+       seq_printf(s, ", error_lt_0 = %u", error_lt0);
+
+       busy = (reg >> RBCPR_RESULT0_BUSY_SHIFT) & 0x01;
+       seq_printf(s, ", busy = %u]\n", busy);
+
+       return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(cpr_debug_info);
+
+static void cpr_debugfs_init(struct cpr_drv *drv)
+{
+       drv->debugfs = debugfs_create_dir("qcom_cpr", NULL);
+
+       debugfs_create_file("debug_info", 0444, drv->debugfs,
+                           drv, &cpr_debug_info_fops);
+}
+
+static int cpr_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct cpr_drv *drv;
+       int irq, ret;
+       const struct cpr_acc_desc *data;
+       struct device_node *np;
+       u32 cpr_rev = FUSE_REVISION_UNKNOWN;
+
+       data = of_device_get_match_data(dev);
+       if (!data || !data->cpr_desc || !data->acc_desc)
+               return -EINVAL;
+
+       drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
+       if (!drv)
+               return -ENOMEM;
+       drv->dev = dev;
+       drv->desc = data->cpr_desc;
+       drv->acc_desc = data->acc_desc;
+
+       drv->fuse_corners = devm_kcalloc(dev, drv->desc->num_fuse_corners,
+                                        sizeof(*drv->fuse_corners),
+                                        GFP_KERNEL);
+       if (!drv->fuse_corners)
+               return -ENOMEM;
+
+       np = of_parse_phandle(dev->of_node, "acc-syscon", 0);
+       if (!np)
+               return -ENODEV;
+
+       drv->tcsr = syscon_node_to_regmap(np);
+       of_node_put(np);
+       if (IS_ERR(drv->tcsr))
+               return PTR_ERR(drv->tcsr);
+
+       drv->base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(drv->base))
+               return PTR_ERR(drv->base);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return -EINVAL;
+
+       drv->vdd_apc = devm_regulator_get(dev, "vdd-apc");
+       if (IS_ERR(drv->vdd_apc))
+               return PTR_ERR(drv->vdd_apc);
+
+       /*
+        * Initialize fuse corners, since it simply depends
+        * on data in efuses.
+        * Everything related to (virtual) corners has to be
+        * initialized after attaching to the power domain,
+        * since it depends on the CPU's OPP table.
+        */
+       ret = nvmem_cell_read_variable_le_u32(dev, "cpr_fuse_revision", &cpr_rev);
+       if (ret)
+               return ret;
+
+       drv->cpr_fuses = cpr_get_fuses(drv);
+       if (IS_ERR(drv->cpr_fuses))
+               return PTR_ERR(drv->cpr_fuses);
+
+       ret = cpr_populate_ring_osc_idx(drv);
+       if (ret)
+               return ret;
+
+       ret = cpr_fuse_corner_init(drv);
+       if (ret)
+               return ret;
+
+       mutex_init(&drv->lock);
+
+       ret = devm_request_threaded_irq(dev, irq, NULL,
+                                       cpr_irq_handler,
+                                       IRQF_ONESHOT | IRQF_TRIGGER_RISING,
+                                       "cpr", drv);
+       if (ret)
+               return ret;
+
+       drv->pd.name = devm_kstrdup_const(dev, dev->of_node->full_name,
+                                         GFP_KERNEL);
+       if (!drv->pd.name)
+               return -EINVAL;
+
+       drv->pd.power_off = cpr_power_off;
+       drv->pd.power_on = cpr_power_on;
+       drv->pd.set_performance_state = cpr_set_performance_state;
+       drv->pd.opp_to_performance_state = cpr_get_performance_state;
+       drv->pd.attach_dev = cpr_pd_attach_dev;
+
+       ret = pm_genpd_init(&drv->pd, NULL, true);
+       if (ret)
+               return ret;
+
+       ret = of_genpd_add_provider_simple(dev->of_node, &drv->pd);
+       if (ret)
+               goto err_remove_genpd;
+
+       platform_set_drvdata(pdev, drv);
+       cpr_debugfs_init(drv);
+
+       return 0;
+
+err_remove_genpd:
+       pm_genpd_remove(&drv->pd);
+       return ret;
+}
+
+static int cpr_remove(struct platform_device *pdev)
+{
+       struct cpr_drv *drv = platform_get_drvdata(pdev);
+
+       if (cpr_is_allowed(drv)) {
+               cpr_ctl_disable(drv);
+               cpr_irq_set(drv, 0);
+       }
+
+       of_genpd_del_provider(pdev->dev.of_node);
+       pm_genpd_remove(&drv->pd);
+
+       debugfs_remove_recursive(drv->debugfs);
+
+       return 0;
+}
+
+static const struct of_device_id cpr_match_table[] = {
+       { .compatible = "qcom,qcs404-cpr", .data = &qcs404_cpr_acc_desc },
+       { }
+};
+MODULE_DEVICE_TABLE(of, cpr_match_table);
+
+static struct platform_driver cpr_driver = {
+       .probe          = cpr_probe,
+       .remove         = cpr_remove,
+       .driver         = {
+               .name   = "qcom-cpr",
+               .of_match_table = cpr_match_table,
+       },
+};
+module_platform_driver(cpr_driver);
+
+MODULE_DESCRIPTION("Core Power Reduction (CPR) driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pmdomain/qcom/rpmhpd.c b/drivers/pmdomain/qcom/rpmhpd.c
new file mode 100644 (file)
index 0000000..a87e336
--- /dev/null
@@ -0,0 +1,886 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.*/
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <soc/qcom/cmd-db.h>
+#include <soc/qcom/rpmh.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
+#include <dt-bindings/power/qcom,rpmhpd.h>
+
+#define domain_to_rpmhpd(domain) container_of(domain, struct rpmhpd, pd)
+
+#define RPMH_ARC_MAX_LEVELS    16
+
+/**
+ * struct rpmhpd - top level RPMh power domain resource data structure
+ * @dev:               rpmh power domain controller device
+ * @pd:                        generic_pm_domain corresponding to the power domain
+ * @parent:            generic_pm_domain corresponding to the parent's power domain
+ * @peer:              A peer power domain in case Active only Voting is
+ *                     supported
+ * @active_only:       True if it represents an Active only peer
+ * @corner:            current corner
+ * @active_corner:     current active corner
+ * @enable_corner:     lowest non-zero corner
+ * @level:             An array of level (vlvl) to corner (hlvl) mappings
+ *                     derived from cmd-db
+ * @level_count:       Number of levels supported by the power domain. max
+ *                     being 16 (0 - 15)
+ * @enabled:           true if the power domain is enabled
+ * @res_name:          Resource name used for cmd-db lookup
+ * @addr:              Resource address as looped up using resource name from
+ *                     cmd-db
+ * @state_synced:      Indicator that sync_state has been invoked for the rpmhpd resource
+ */
+struct rpmhpd {
+       struct device   *dev;
+       struct generic_pm_domain pd;
+       struct generic_pm_domain *parent;
+       struct rpmhpd   *peer;
+       const bool      active_only;
+       unsigned int    corner;
+       unsigned int    active_corner;
+       unsigned int    enable_corner;
+       u32             level[RPMH_ARC_MAX_LEVELS];
+       size_t          level_count;
+       bool            enabled;
+       const char      *res_name;
+       u32             addr;
+       bool            state_synced;
+};
+
+struct rpmhpd_desc {
+       struct rpmhpd **rpmhpds;
+       size_t num_pds;
+};
+
+static DEFINE_MUTEX(rpmhpd_lock);
+
+/* RPMH powerdomains */
+
+static struct rpmhpd cx_ao;
+static struct rpmhpd mx;
+static struct rpmhpd mx_ao;
+static struct rpmhpd cx = {
+       .pd = { .name = "cx", },
+       .peer = &cx_ao,
+       .res_name = "cx.lvl",
+};
+
+static struct rpmhpd cx_ao = {
+       .pd = { .name = "cx_ao", },
+       .active_only = true,
+       .peer = &cx,
+       .res_name = "cx.lvl",
+};
+
+static struct rpmhpd cx_ao_w_mx_parent;
+static struct rpmhpd cx_w_mx_parent = {
+       .pd = { .name = "cx", },
+       .peer = &cx_ao_w_mx_parent,
+       .parent = &mx.pd,
+       .res_name = "cx.lvl",
+};
+
+static struct rpmhpd cx_ao_w_mx_parent = {
+       .pd = { .name = "cx_ao", },
+       .active_only = true,
+       .peer = &cx_w_mx_parent,
+       .parent = &mx_ao.pd,
+       .res_name = "cx.lvl",
+};
+
+static struct rpmhpd ebi = {
+       .pd = { .name = "ebi", },
+       .res_name = "ebi.lvl",
+};
+
+static struct rpmhpd gfx = {
+       .pd = { .name = "gfx", },
+       .res_name = "gfx.lvl",
+};
+
+static struct rpmhpd lcx = {
+       .pd = { .name = "lcx", },
+       .res_name = "lcx.lvl",
+};
+
+static struct rpmhpd lmx = {
+       .pd = { .name = "lmx", },
+       .res_name = "lmx.lvl",
+};
+
+static struct rpmhpd mmcx_ao;
+static struct rpmhpd mmcx = {
+       .pd = { .name = "mmcx", },
+       .peer = &mmcx_ao,
+       .res_name = "mmcx.lvl",
+};
+
+static struct rpmhpd mmcx_ao = {
+       .pd = { .name = "mmcx_ao", },
+       .active_only = true,
+       .peer = &mmcx,
+       .res_name = "mmcx.lvl",
+};
+
+static struct rpmhpd mmcx_ao_w_cx_parent;
+static struct rpmhpd mmcx_w_cx_parent = {
+       .pd = { .name = "mmcx", },
+       .peer = &mmcx_ao_w_cx_parent,
+       .parent = &cx.pd,
+       .res_name = "mmcx.lvl",
+};
+
+static struct rpmhpd mmcx_ao_w_cx_parent = {
+       .pd = { .name = "mmcx_ao", },
+       .active_only = true,
+       .peer = &mmcx_w_cx_parent,
+       .parent = &cx_ao.pd,
+       .res_name = "mmcx.lvl",
+};
+
+static struct rpmhpd mss = {
+       .pd = { .name = "mss", },
+       .res_name = "mss.lvl",
+};
+
+static struct rpmhpd mx_ao;
+static struct rpmhpd mx = {
+       .pd = { .name = "mx", },
+       .peer = &mx_ao,
+       .res_name = "mx.lvl",
+};
+
+static struct rpmhpd mx_ao = {
+       .pd = { .name = "mx_ao", },
+       .active_only = true,
+       .peer = &mx,
+       .res_name = "mx.lvl",
+};
+
+static struct rpmhpd mxc_ao;
+static struct rpmhpd mxc = {
+       .pd = { .name = "mxc", },
+       .peer = &mxc_ao,
+       .res_name = "mxc.lvl",
+};
+
+static struct rpmhpd mxc_ao = {
+       .pd = { .name = "mxc_ao", },
+       .active_only = true,
+       .peer = &mxc,
+       .res_name = "mxc.lvl",
+};
+
+static struct rpmhpd nsp = {
+       .pd = { .name = "nsp", },
+       .res_name = "nsp.lvl",
+};
+
+static struct rpmhpd nsp0 = {
+       .pd = { .name = "nsp0", },
+       .res_name = "nsp0.lvl",
+};
+
+static struct rpmhpd nsp1 = {
+       .pd = { .name = "nsp1", },
+       .res_name = "nsp1.lvl",
+};
+
+static struct rpmhpd qphy = {
+       .pd = { .name = "qphy", },
+       .res_name = "qphy.lvl",
+};
+
+/* SA8540P RPMH powerdomains */
+static struct rpmhpd *sa8540p_rpmhpds[] = {
+       [SC8280XP_CX] = &cx,
+       [SC8280XP_CX_AO] = &cx_ao,
+       [SC8280XP_EBI] = &ebi,
+       [SC8280XP_GFX] = &gfx,
+       [SC8280XP_LCX] = &lcx,
+       [SC8280XP_LMX] = &lmx,
+       [SC8280XP_MMCX] = &mmcx,
+       [SC8280XP_MMCX_AO] = &mmcx_ao,
+       [SC8280XP_MX] = &mx,
+       [SC8280XP_MX_AO] = &mx_ao,
+       [SC8280XP_NSP] = &nsp,
+};
+
+static const struct rpmhpd_desc sa8540p_desc = {
+       .rpmhpds = sa8540p_rpmhpds,
+       .num_pds = ARRAY_SIZE(sa8540p_rpmhpds),
+};
+
+/* SA8775P RPMH power domains */
+static struct rpmhpd *sa8775p_rpmhpds[] = {
+       [SA8775P_CX] = &cx,
+       [SA8775P_CX_AO] = &cx_ao,
+       [SA8775P_EBI] = &ebi,
+       [SA8775P_GFX] = &gfx,
+       [SA8775P_LCX] = &lcx,
+       [SA8775P_LMX] = &lmx,
+       [SA8775P_MMCX] = &mmcx,
+       [SA8775P_MMCX_AO] = &mmcx_ao,
+       [SA8775P_MXC] = &mxc,
+       [SA8775P_MXC_AO] = &mxc_ao,
+       [SA8775P_MX] = &mx,
+       [SA8775P_MX_AO] = &mx_ao,
+       [SA8775P_NSP0] = &nsp0,
+       [SA8775P_NSP1] = &nsp1,
+};
+
+static const struct rpmhpd_desc sa8775p_desc = {
+       .rpmhpds = sa8775p_rpmhpds,
+       .num_pds = ARRAY_SIZE(sa8775p_rpmhpds),
+};
+
+/* SDM670 RPMH powerdomains */
+static struct rpmhpd *sdm670_rpmhpds[] = {
+       [SDM670_CX] = &cx_w_mx_parent,
+       [SDM670_CX_AO] = &cx_ao_w_mx_parent,
+       [SDM670_GFX] = &gfx,
+       [SDM670_LCX] = &lcx,
+       [SDM670_LMX] = &lmx,
+       [SDM670_MSS] = &mss,
+       [SDM670_MX] = &mx,
+       [SDM670_MX_AO] = &mx_ao,
+};
+
+static const struct rpmhpd_desc sdm670_desc = {
+       .rpmhpds = sdm670_rpmhpds,
+       .num_pds = ARRAY_SIZE(sdm670_rpmhpds),
+};
+
+/* SDM845 RPMH powerdomains */
+static struct rpmhpd *sdm845_rpmhpds[] = {
+       [SDM845_CX] = &cx_w_mx_parent,
+       [SDM845_CX_AO] = &cx_ao_w_mx_parent,
+       [SDM845_EBI] = &ebi,
+       [SDM845_GFX] = &gfx,
+       [SDM845_LCX] = &lcx,
+       [SDM845_LMX] = &lmx,
+       [SDM845_MSS] = &mss,
+       [SDM845_MX] = &mx,
+       [SDM845_MX_AO] = &mx_ao,
+};
+
+static const struct rpmhpd_desc sdm845_desc = {
+       .rpmhpds = sdm845_rpmhpds,
+       .num_pds = ARRAY_SIZE(sdm845_rpmhpds),
+};
+
+/* SDX55 RPMH powerdomains */
+static struct rpmhpd *sdx55_rpmhpds[] = {
+       [SDX55_CX] = &cx_w_mx_parent,
+       [SDX55_MSS] = &mss,
+       [SDX55_MX] = &mx,
+};
+
+static const struct rpmhpd_desc sdx55_desc = {
+       .rpmhpds = sdx55_rpmhpds,
+       .num_pds = ARRAY_SIZE(sdx55_rpmhpds),
+};
+
+/* SDX65 RPMH powerdomains */
+static struct rpmhpd *sdx65_rpmhpds[] = {
+       [SDX65_CX] = &cx_w_mx_parent,
+       [SDX65_CX_AO] = &cx_ao_w_mx_parent,
+       [SDX65_MSS] = &mss,
+       [SDX65_MX] = &mx,
+       [SDX65_MX_AO] = &mx_ao,
+       [SDX65_MXC] = &mxc,
+};
+
+static const struct rpmhpd_desc sdx65_desc = {
+       .rpmhpds = sdx65_rpmhpds,
+       .num_pds = ARRAY_SIZE(sdx65_rpmhpds),
+};
+
+/* SDX75 RPMH powerdomains */
+static struct rpmhpd *sdx75_rpmhpds[] = {
+       [RPMHPD_CX] = &cx,
+       [RPMHPD_CX_AO] = &cx_ao,
+       [RPMHPD_MSS] = &mss,
+       [RPMHPD_MX] = &mx,
+       [RPMHPD_MX_AO] = &mx_ao,
+       [RPMHPD_MXC] = &mxc,
+};
+
+static const struct rpmhpd_desc sdx75_desc = {
+       .rpmhpds = sdx75_rpmhpds,
+       .num_pds = ARRAY_SIZE(sdx75_rpmhpds),
+};
+
+/* SM6350 RPMH powerdomains */
+static struct rpmhpd *sm6350_rpmhpds[] = {
+       [SM6350_CX] = &cx_w_mx_parent,
+       [SM6350_GFX] = &gfx,
+       [SM6350_LCX] = &lcx,
+       [SM6350_LMX] = &lmx,
+       [SM6350_MSS] = &mss,
+       [SM6350_MX] = &mx,
+};
+
+static const struct rpmhpd_desc sm6350_desc = {
+       .rpmhpds = sm6350_rpmhpds,
+       .num_pds = ARRAY_SIZE(sm6350_rpmhpds),
+};
+
+/* SM8150 RPMH powerdomains */
+static struct rpmhpd *sm8150_rpmhpds[] = {
+       [SM8150_CX] = &cx_w_mx_parent,
+       [SM8150_CX_AO] = &cx_ao_w_mx_parent,
+       [SM8150_EBI] = &ebi,
+       [SM8150_GFX] = &gfx,
+       [SM8150_LCX] = &lcx,
+       [SM8150_LMX] = &lmx,
+       [SM8150_MMCX] = &mmcx,
+       [SM8150_MMCX_AO] = &mmcx_ao,
+       [SM8150_MSS] = &mss,
+       [SM8150_MX] = &mx,
+       [SM8150_MX_AO] = &mx_ao,
+};
+
+static const struct rpmhpd_desc sm8150_desc = {
+       .rpmhpds = sm8150_rpmhpds,
+       .num_pds = ARRAY_SIZE(sm8150_rpmhpds),
+};
+
+static struct rpmhpd *sa8155p_rpmhpds[] = {
+       [SA8155P_CX] = &cx_w_mx_parent,
+       [SA8155P_CX_AO] = &cx_ao_w_mx_parent,
+       [SA8155P_EBI] = &ebi,
+       [SA8155P_GFX] = &gfx,
+       [SA8155P_MSS] = &mss,
+       [SA8155P_MX] = &mx,
+       [SA8155P_MX_AO] = &mx_ao,
+};
+
+static const struct rpmhpd_desc sa8155p_desc = {
+       .rpmhpds = sa8155p_rpmhpds,
+       .num_pds = ARRAY_SIZE(sa8155p_rpmhpds),
+};
+
+/* SM8250 RPMH powerdomains */
+static struct rpmhpd *sm8250_rpmhpds[] = {
+       [RPMHPD_CX] = &cx_w_mx_parent,
+       [RPMHPD_CX_AO] = &cx_ao_w_mx_parent,
+       [RPMHPD_EBI] = &ebi,
+       [RPMHPD_GFX] = &gfx,
+       [RPMHPD_LCX] = &lcx,
+       [RPMHPD_LMX] = &lmx,
+       [RPMHPD_MMCX] = &mmcx,
+       [RPMHPD_MMCX_AO] = &mmcx_ao,
+       [RPMHPD_MX] = &mx,
+       [RPMHPD_MX_AO] = &mx_ao,
+};
+
+static const struct rpmhpd_desc sm8250_desc = {
+       .rpmhpds = sm8250_rpmhpds,
+       .num_pds = ARRAY_SIZE(sm8250_rpmhpds),
+};
+
+/* SM8350 Power domains */
+static struct rpmhpd *sm8350_rpmhpds[] = {
+       [RPMHPD_CX] = &cx_w_mx_parent,
+       [RPMHPD_CX_AO] = &cx_ao_w_mx_parent,
+       [RPMHPD_EBI] = &ebi,
+       [RPMHPD_GFX] = &gfx,
+       [RPMHPD_LCX] = &lcx,
+       [RPMHPD_LMX] = &lmx,
+       [RPMHPD_MMCX] = &mmcx,
+       [RPMHPD_MMCX_AO] = &mmcx_ao,
+       [RPMHPD_MSS] = &mss,
+       [RPMHPD_MX] = &mx,
+       [RPMHPD_MX_AO] = &mx_ao,
+       [RPMHPD_MXC] = &mxc,
+       [RPMHPD_MXC_AO] = &mxc_ao,
+};
+
+static const struct rpmhpd_desc sm8350_desc = {
+       .rpmhpds = sm8350_rpmhpds,
+       .num_pds = ARRAY_SIZE(sm8350_rpmhpds),
+};
+
+/* SM8450 RPMH powerdomains */
+static struct rpmhpd *sm8450_rpmhpds[] = {
+       [RPMHPD_CX] = &cx,
+       [RPMHPD_CX_AO] = &cx_ao,
+       [RPMHPD_EBI] = &ebi,
+       [RPMHPD_GFX] = &gfx,
+       [RPMHPD_LCX] = &lcx,
+       [RPMHPD_LMX] = &lmx,
+       [RPMHPD_MMCX] = &mmcx_w_cx_parent,
+       [RPMHPD_MMCX_AO] = &mmcx_ao_w_cx_parent,
+       [RPMHPD_MSS] = &mss,
+       [RPMHPD_MX] = &mx,
+       [RPMHPD_MX_AO] = &mx_ao,
+       [RPMHPD_MXC] = &mxc,
+       [RPMHPD_MXC_AO] = &mxc_ao,
+};
+
+static const struct rpmhpd_desc sm8450_desc = {
+       .rpmhpds = sm8450_rpmhpds,
+       .num_pds = ARRAY_SIZE(sm8450_rpmhpds),
+};
+
+/* SM8550 RPMH powerdomains */
+static struct rpmhpd *sm8550_rpmhpds[] = {
+       [RPMHPD_CX] = &cx,
+       [RPMHPD_CX_AO] = &cx_ao,
+       [RPMHPD_EBI] = &ebi,
+       [RPMHPD_GFX] = &gfx,
+       [RPMHPD_LCX] = &lcx,
+       [RPMHPD_LMX] = &lmx,
+       [RPMHPD_MMCX] = &mmcx_w_cx_parent,
+       [RPMHPD_MMCX_AO] = &mmcx_ao_w_cx_parent,
+       [RPMHPD_MSS] = &mss,
+       [RPMHPD_MX] = &mx,
+       [RPMHPD_MX_AO] = &mx_ao,
+       [RPMHPD_MXC] = &mxc,
+       [RPMHPD_MXC_AO] = &mxc_ao,
+       [RPMHPD_NSP] = &nsp,
+};
+
+static const struct rpmhpd_desc sm8550_desc = {
+       .rpmhpds = sm8550_rpmhpds,
+       .num_pds = ARRAY_SIZE(sm8550_rpmhpds),
+};
+
+/* QDU1000/QRU1000 RPMH powerdomains */
+static struct rpmhpd *qdu1000_rpmhpds[] = {
+       [QDU1000_CX] = &cx,
+       [QDU1000_EBI] = &ebi,
+       [QDU1000_MSS] = &mss,
+       [QDU1000_MX] = &mx,
+};
+
+static const struct rpmhpd_desc qdu1000_desc = {
+       .rpmhpds = qdu1000_rpmhpds,
+       .num_pds = ARRAY_SIZE(qdu1000_rpmhpds),
+};
+
+/* SC7180 RPMH powerdomains */
+static struct rpmhpd *sc7180_rpmhpds[] = {
+       [SC7180_CX] = &cx_w_mx_parent,
+       [SC7180_CX_AO] = &cx_ao_w_mx_parent,
+       [SC7180_GFX] = &gfx,
+       [SC7180_LCX] = &lcx,
+       [SC7180_LMX] = &lmx,
+       [SC7180_MSS] = &mss,
+       [SC7180_MX] = &mx,
+       [SC7180_MX_AO] = &mx_ao,
+};
+
+static const struct rpmhpd_desc sc7180_desc = {
+       .rpmhpds = sc7180_rpmhpds,
+       .num_pds = ARRAY_SIZE(sc7180_rpmhpds),
+};
+
+/* SC7280 RPMH powerdomains */
+static struct rpmhpd *sc7280_rpmhpds[] = {
+       [SC7280_CX] = &cx,
+       [SC7280_CX_AO] = &cx_ao,
+       [SC7280_EBI] = &ebi,
+       [SC7280_GFX] = &gfx,
+       [SC7280_LCX] = &lcx,
+       [SC7280_LMX] = &lmx,
+       [SC7280_MSS] = &mss,
+       [SC7280_MX] = &mx,
+       [SC7280_MX_AO] = &mx_ao,
+};
+
+static const struct rpmhpd_desc sc7280_desc = {
+       .rpmhpds = sc7280_rpmhpds,
+       .num_pds = ARRAY_SIZE(sc7280_rpmhpds),
+};
+
+/* SC8180x RPMH powerdomains */
+static struct rpmhpd *sc8180x_rpmhpds[] = {
+       [SC8180X_CX] = &cx_w_mx_parent,
+       [SC8180X_CX_AO] = &cx_ao_w_mx_parent,
+       [SC8180X_EBI] = &ebi,
+       [SC8180X_GFX] = &gfx,
+       [SC8180X_LCX] = &lcx,
+       [SC8180X_LMX] = &lmx,
+       [SC8180X_MMCX] = &mmcx,
+       [SC8180X_MMCX_AO] = &mmcx_ao,
+       [SC8180X_MSS] = &mss,
+       [SC8180X_MX] = &mx,
+       [SC8180X_MX_AO] = &mx_ao,
+};
+
+static const struct rpmhpd_desc sc8180x_desc = {
+       .rpmhpds = sc8180x_rpmhpds,
+       .num_pds = ARRAY_SIZE(sc8180x_rpmhpds),
+};
+
+/* SC8280xp RPMH powerdomains */
+static struct rpmhpd *sc8280xp_rpmhpds[] = {
+       [SC8280XP_CX] = &cx,
+       [SC8280XP_CX_AO] = &cx_ao,
+       [SC8280XP_EBI] = &ebi,
+       [SC8280XP_GFX] = &gfx,
+       [SC8280XP_LCX] = &lcx,
+       [SC8280XP_LMX] = &lmx,
+       [SC8280XP_MMCX] = &mmcx,
+       [SC8280XP_MMCX_AO] = &mmcx_ao,
+       [SC8280XP_MX] = &mx,
+       [SC8280XP_MX_AO] = &mx_ao,
+       [SC8280XP_NSP] = &nsp,
+       [SC8280XP_QPHY] = &qphy,
+};
+
+static const struct rpmhpd_desc sc8280xp_desc = {
+       .rpmhpds = sc8280xp_rpmhpds,
+       .num_pds = ARRAY_SIZE(sc8280xp_rpmhpds),
+};
+
+static const struct of_device_id rpmhpd_match_table[] = {
+       { .compatible = "qcom,qdu1000-rpmhpd", .data = &qdu1000_desc },
+       { .compatible = "qcom,sa8155p-rpmhpd", .data = &sa8155p_desc },
+       { .compatible = "qcom,sa8540p-rpmhpd", .data = &sa8540p_desc },
+       { .compatible = "qcom,sa8775p-rpmhpd", .data = &sa8775p_desc },
+       { .compatible = "qcom,sc7180-rpmhpd", .data = &sc7180_desc },
+       { .compatible = "qcom,sc7280-rpmhpd", .data = &sc7280_desc },
+       { .compatible = "qcom,sc8180x-rpmhpd", .data = &sc8180x_desc },
+       { .compatible = "qcom,sc8280xp-rpmhpd", .data = &sc8280xp_desc },
+       { .compatible = "qcom,sdm670-rpmhpd", .data = &sdm670_desc },
+       { .compatible = "qcom,sdm845-rpmhpd", .data = &sdm845_desc },
+       { .compatible = "qcom,sdx55-rpmhpd", .data = &sdx55_desc},
+       { .compatible = "qcom,sdx65-rpmhpd", .data = &sdx65_desc},
+       { .compatible = "qcom,sdx75-rpmhpd", .data = &sdx75_desc},
+       { .compatible = "qcom,sm6350-rpmhpd", .data = &sm6350_desc },
+       { .compatible = "qcom,sm8150-rpmhpd", .data = &sm8150_desc },
+       { .compatible = "qcom,sm8250-rpmhpd", .data = &sm8250_desc },
+       { .compatible = "qcom,sm8350-rpmhpd", .data = &sm8350_desc },
+       { .compatible = "qcom,sm8450-rpmhpd", .data = &sm8450_desc },
+       { .compatible = "qcom,sm8550-rpmhpd", .data = &sm8550_desc },
+       { }
+};
+MODULE_DEVICE_TABLE(of, rpmhpd_match_table);
+
+static int rpmhpd_send_corner(struct rpmhpd *pd, int state,
+                             unsigned int corner, bool sync)
+{
+       struct tcs_cmd cmd = {
+               .addr = pd->addr,
+               .data = corner,
+       };
+
+       /*
+        * Wait for an ack only when we are increasing the
+        * perf state of the power domain
+        */
+       if (sync)
+               return rpmh_write(pd->dev, state, &cmd, 1);
+       else
+               return rpmh_write_async(pd->dev, state, &cmd, 1);
+}
+
+static void to_active_sleep(struct rpmhpd *pd, unsigned int corner,
+                           unsigned int *active, unsigned int *sleep)
+{
+       *active = corner;
+
+       if (pd->active_only)
+               *sleep = 0;
+       else
+               *sleep = *active;
+}
+
+/*
+ * This function is used to aggregate the votes across the active only
+ * resources and its peers. The aggregated votes are sent to RPMh as
+ * ACTIVE_ONLY votes (which take effect immediately), as WAKE_ONLY votes
+ * (applied by RPMh on system wakeup) and as SLEEP votes (applied by RPMh
+ * on system sleep).
+ * We send ACTIVE_ONLY votes for resources without any peers. For others,
+ * which have an active only peer, all 3 votes are sent.
+ */
+static int rpmhpd_aggregate_corner(struct rpmhpd *pd, unsigned int corner)
+{
+       int ret;
+       struct rpmhpd *peer = pd->peer;
+       unsigned int active_corner, sleep_corner;
+       unsigned int this_active_corner = 0, this_sleep_corner = 0;
+       unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
+
+       if (pd->state_synced) {
+               to_active_sleep(pd, corner, &this_active_corner, &this_sleep_corner);
+       } else {
+               /* Clamp to highest corner if sync_state hasn't happened */
+               this_active_corner = pd->level_count - 1;
+               this_sleep_corner = pd->level_count - 1;
+       }
+
+       if (peer && peer->enabled)
+               to_active_sleep(peer, peer->corner, &peer_active_corner,
+                               &peer_sleep_corner);
+
+       active_corner = max(this_active_corner, peer_active_corner);
+
+       ret = rpmhpd_send_corner(pd, RPMH_ACTIVE_ONLY_STATE, active_corner,
+                                active_corner > pd->active_corner);
+       if (ret)
+               return ret;
+
+       pd->active_corner = active_corner;
+
+       if (peer) {
+               peer->active_corner = active_corner;
+
+               ret = rpmhpd_send_corner(pd, RPMH_WAKE_ONLY_STATE,
+                                        active_corner, false);
+               if (ret)
+                       return ret;
+
+               sleep_corner = max(this_sleep_corner, peer_sleep_corner);
+
+               return rpmhpd_send_corner(pd, RPMH_SLEEP_STATE, sleep_corner,
+                                         false);
+       }
+
+       return ret;
+}
+
+static int rpmhpd_power_on(struct generic_pm_domain *domain)
+{
+       struct rpmhpd *pd = domain_to_rpmhpd(domain);
+       unsigned int corner;
+       int ret;
+
+       mutex_lock(&rpmhpd_lock);
+
+       corner = max(pd->corner, pd->enable_corner);
+       ret = rpmhpd_aggregate_corner(pd, corner);
+       if (!ret)
+               pd->enabled = true;
+
+       mutex_unlock(&rpmhpd_lock);
+
+       return ret;
+}
+
+static int rpmhpd_power_off(struct generic_pm_domain *domain)
+{
+       struct rpmhpd *pd = domain_to_rpmhpd(domain);
+       int ret;
+
+       mutex_lock(&rpmhpd_lock);
+
+       ret = rpmhpd_aggregate_corner(pd, 0);
+       if (!ret)
+               pd->enabled = false;
+
+       mutex_unlock(&rpmhpd_lock);
+
+       return ret;
+}
+
+static int rpmhpd_set_performance_state(struct generic_pm_domain *domain,
+                                       unsigned int level)
+{
+       struct rpmhpd *pd = domain_to_rpmhpd(domain);
+       int ret = 0, i;
+
+       mutex_lock(&rpmhpd_lock);
+
+       for (i = 0; i < pd->level_count; i++)
+               if (level <= pd->level[i])
+                       break;
+
+       /*
+        * If the level requested is more than that supported by the
+        * max corner, just set it to max anyway.
+        */
+       if (i == pd->level_count)
+               i--;
+
+       if (pd->enabled) {
+               /* Ensure that the domain isn't turn off */
+               if (i < pd->enable_corner)
+                       i = pd->enable_corner;
+
+               ret = rpmhpd_aggregate_corner(pd, i);
+               if (ret)
+                       goto out;
+       }
+
+       pd->corner = i;
+out:
+       mutex_unlock(&rpmhpd_lock);
+
+       return ret;
+}
+
+static unsigned int rpmhpd_get_performance_state(struct generic_pm_domain *genpd,
+                                                struct dev_pm_opp *opp)
+{
+       return dev_pm_opp_get_level(opp);
+}
+
+static int rpmhpd_update_level_mapping(struct rpmhpd *rpmhpd)
+{
+       int i;
+       const u16 *buf;
+
+       buf = cmd_db_read_aux_data(rpmhpd->res_name, &rpmhpd->level_count);
+       if (IS_ERR(buf))
+               return PTR_ERR(buf);
+
+       /* 2 bytes used for each command DB aux data entry */
+       rpmhpd->level_count >>= 1;
+
+       if (rpmhpd->level_count > RPMH_ARC_MAX_LEVELS)
+               return -EINVAL;
+
+       for (i = 0; i < rpmhpd->level_count; i++) {
+               rpmhpd->level[i] = buf[i];
+
+               /* Remember the first corner with non-zero level */
+               if (!rpmhpd->level[rpmhpd->enable_corner] && rpmhpd->level[i])
+                       rpmhpd->enable_corner = i;
+
+               /*
+                * The AUX data may be zero padded.  These 0 valued entries at
+                * the end of the map must be ignored.
+                */
+               if (i > 0 && rpmhpd->level[i] == 0) {
+                       rpmhpd->level_count = i;
+                       break;
+               }
+               pr_debug("%s: ARC hlvl=%2d --> vlvl=%4u\n", rpmhpd->res_name, i,
+                        rpmhpd->level[i]);
+       }
+
+       return 0;
+}
+
+static int rpmhpd_probe(struct platform_device *pdev)
+{
+       int i, ret;
+       size_t num_pds;
+       struct device *dev = &pdev->dev;
+       struct genpd_onecell_data *data;
+       struct rpmhpd **rpmhpds;
+       const struct rpmhpd_desc *desc;
+
+       desc = of_device_get_match_data(dev);
+       if (!desc)
+               return -EINVAL;
+
+       rpmhpds = desc->rpmhpds;
+       num_pds = desc->num_pds;
+
+       data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       data->domains = devm_kcalloc(dev, num_pds, sizeof(*data->domains),
+                                    GFP_KERNEL);
+       if (!data->domains)
+               return -ENOMEM;
+
+       data->num_domains = num_pds;
+
+       for (i = 0; i < num_pds; i++) {
+               if (!rpmhpds[i])
+                       continue;
+
+               rpmhpds[i]->dev = dev;
+               rpmhpds[i]->addr = cmd_db_read_addr(rpmhpds[i]->res_name);
+               if (!rpmhpds[i]->addr) {
+                       dev_err(dev, "Could not find RPMh address for resource %s\n",
+                               rpmhpds[i]->res_name);
+                       return -ENODEV;
+               }
+
+               ret = cmd_db_read_slave_id(rpmhpds[i]->res_name);
+               if (ret != CMD_DB_HW_ARC) {
+                       dev_err(dev, "RPMh slave ID mismatch\n");
+                       return -EINVAL;
+               }
+
+               ret = rpmhpd_update_level_mapping(rpmhpds[i]);
+               if (ret)
+                       return ret;
+
+               rpmhpds[i]->pd.power_off = rpmhpd_power_off;
+               rpmhpds[i]->pd.power_on = rpmhpd_power_on;
+               rpmhpds[i]->pd.set_performance_state = rpmhpd_set_performance_state;
+               rpmhpds[i]->pd.opp_to_performance_state = rpmhpd_get_performance_state;
+               pm_genpd_init(&rpmhpds[i]->pd, NULL, true);
+
+               data->domains[i] = &rpmhpds[i]->pd;
+       }
+
+       /* Add subdomains */
+       for (i = 0; i < num_pds; i++) {
+               if (!rpmhpds[i])
+                       continue;
+               if (rpmhpds[i]->parent)
+                       pm_genpd_add_subdomain(rpmhpds[i]->parent,
+                                              &rpmhpds[i]->pd);
+       }
+
+       return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
+}
+
+static void rpmhpd_sync_state(struct device *dev)
+{
+       const struct rpmhpd_desc *desc = of_device_get_match_data(dev);
+       struct rpmhpd **rpmhpds = desc->rpmhpds;
+       unsigned int corner;
+       struct rpmhpd *pd;
+       unsigned int i;
+       int ret;
+
+       mutex_lock(&rpmhpd_lock);
+       for (i = 0; i < desc->num_pds; i++) {
+               pd = rpmhpds[i];
+               if (!pd)
+                       continue;
+
+               pd->state_synced = true;
+               if (pd->enabled)
+                       corner = max(pd->corner, pd->enable_corner);
+               else
+                       corner = 0;
+
+               ret = rpmhpd_aggregate_corner(pd, corner);
+               if (ret)
+                       dev_err(dev, "failed to sync %s\n", pd->res_name);
+       }
+       mutex_unlock(&rpmhpd_lock);
+}
+
+static struct platform_driver rpmhpd_driver = {
+       .driver = {
+               .name = "qcom-rpmhpd",
+               .of_match_table = rpmhpd_match_table,
+               .suppress_bind_attrs = true,
+               .sync_state = rpmhpd_sync_state,
+       },
+       .probe = rpmhpd_probe,
+};
+
+static int __init rpmhpd_init(void)
+{
+       return platform_driver_register(&rpmhpd_driver);
+}
+core_initcall(rpmhpd_init);
+
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPMh Power Domain Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pmdomain/qcom/rpmpd.c b/drivers/pmdomain/qcom/rpmpd.c
new file mode 100644 (file)
index 0000000..3135dd1
--- /dev/null
@@ -0,0 +1,1023 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/pm_domain.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/soc/qcom/smd-rpm.h>
+
+#include <dt-bindings/power/qcom-rpmpd.h>
+
+#define domain_to_rpmpd(domain) container_of(domain, struct rpmpd, pd)
+
+/* Resource types:
+ * RPMPD_X is X encoded as a little-endian, lower-case, ASCII string */
+#define RPMPD_SMPA 0x61706d73
+#define RPMPD_LDOA 0x616f646c
+#define RPMPD_SMPB 0x62706d73
+#define RPMPD_LDOB 0x626f646c
+#define RPMPD_RWCX 0x78637772
+#define RPMPD_RWMX 0x786d7772
+#define RPMPD_RWLC 0x636c7772
+#define RPMPD_RWLM 0x6d6c7772
+#define RPMPD_RWSC 0x63737772
+#define RPMPD_RWSM 0x6d737772
+#define RPMPD_RWGX 0x78677772
+
+/* Operation Keys */
+#define KEY_CORNER             0x6e726f63 /* corn */
+#define KEY_ENABLE             0x6e657773 /* swen */
+#define KEY_FLOOR_CORNER       0x636676   /* vfc */
+#define KEY_FLOOR_LEVEL                0x6c6676   /* vfl */
+#define KEY_LEVEL              0x6c766c76 /* vlvl */
+
+#define MAX_CORNER_RPMPD_STATE 6
+
+struct rpmpd_req {
+       __le32 key;
+       __le32 nbytes;
+       __le32 value;
+};
+
+struct rpmpd {
+       struct generic_pm_domain pd;
+       struct generic_pm_domain *parent;
+       struct rpmpd *peer;
+       const bool active_only;
+       unsigned int corner;
+       bool enabled;
+       const int res_type;
+       const int res_id;
+       struct qcom_smd_rpm *rpm;
+       unsigned int max_state;
+       __le32 key;
+       bool state_synced;
+};
+
+struct rpmpd_desc {
+       struct rpmpd **rpmpds;
+       size_t num_pds;
+       unsigned int max_state;
+};
+
+static DEFINE_MUTEX(rpmpd_lock);
+
+/* CX */
+static struct rpmpd cx_rwcx0_lvl_ao;
+static struct rpmpd cx_rwcx0_lvl = {
+       .pd = { .name = "cx", },
+       .peer = &cx_rwcx0_lvl_ao,
+       .res_type = RPMPD_RWCX,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_rwcx0_lvl_ao = {
+       .pd = { .name = "cx_ao", },
+       .peer = &cx_rwcx0_lvl,
+       .active_only = true,
+       .res_type = RPMPD_RWCX,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_s1a_corner_ao;
+static struct rpmpd cx_s1a_corner = {
+       .pd = { .name = "cx", },
+       .peer = &cx_s1a_corner_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd cx_s1a_corner_ao = {
+       .pd = { .name = "cx_ao", },
+       .peer = &cx_s1a_corner,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd cx_s2a_corner_ao;
+static struct rpmpd cx_s2a_corner = {
+       .pd = { .name = "cx", },
+       .peer = &cx_s2a_corner_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd cx_s2a_corner_ao = {
+       .pd = { .name = "cx_ao", },
+       .peer = &cx_s2a_corner,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd cx_s2a_lvl_ao;
+static struct rpmpd cx_s2a_lvl = {
+       .pd = { .name = "cx", },
+       .peer = &cx_s2a_lvl_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_s2a_lvl_ao = {
+       .pd = { .name = "cx_ao", },
+       .peer = &cx_s2a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_s3a_lvl_ao;
+static struct rpmpd cx_s3a_lvl = {
+       .pd = { .name = "cx", },
+       .peer = &cx_s3a_lvl_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 3,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_s3a_lvl_ao = {
+       .pd = { .name = "cx_ao", },
+       .peer = &cx_s3a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 3,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_rwcx0_vfl = {
+       .pd = { .name = "cx_vfl", },
+       .res_type = RPMPD_RWCX,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd cx_rwsc2_vfl = {
+       .pd = { .name = "cx_vfl", },
+       .res_type = RPMPD_RWSC,
+       .res_id = 2,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd cx_s1a_vfc = {
+       .pd = { .name = "cx_vfc", },
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_FLOOR_CORNER,
+};
+
+static struct rpmpd cx_s2a_vfc = {
+       .pd = { .name = "cx_vfc", },
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_FLOOR_CORNER,
+};
+
+static struct rpmpd cx_s2a_vfl = {
+       .pd = { .name = "cx_vfl", },
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd cx_s3a_vfl = {
+       .pd = { .name = "cx_vfl", },
+       .res_type = RPMPD_SMPA,
+       .res_id = 3,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+/* G(F)X */
+static struct rpmpd gfx_s2b_corner = {
+       .pd = { .name = "gfx", },
+       .res_type = RPMPD_SMPB,
+       .res_id = 2,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd gfx_s2b_vfc = {
+       .pd = { .name = "gfx_vfc", },
+       .res_type = RPMPD_SMPB,
+       .res_id = 2,
+       .key = KEY_FLOOR_CORNER,
+};
+
+static struct rpmpd mx_rwmx0_lvl;
+static struct rpmpd gx_rwgx0_lvl_ao;
+static struct rpmpd gx_rwgx0_lvl = {
+       .pd = { .name = "gx", },
+       .peer = &gx_rwgx0_lvl_ao,
+       .res_type = RPMPD_RWGX,
+       .parent = &mx_rwmx0_lvl.pd,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_rwmx0_lvl_ao;
+static struct rpmpd gx_rwgx0_lvl_ao = {
+       .pd = { .name = "gx_ao", },
+       .peer = &gx_rwgx0_lvl,
+       .parent = &mx_rwmx0_lvl_ao.pd,
+       .active_only = true,
+       .res_type = RPMPD_RWGX,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+/* MX */
+static struct rpmpd mx_l3a_corner_ao;
+static struct rpmpd mx_l3a_corner = {
+       .pd = { .name = "mx", },
+       .peer = &mx_l3a_corner_ao,
+       .res_type = RPMPD_LDOA,
+       .res_id = 3,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd mx_l3a_corner_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_l3a_corner,
+       .active_only = true,
+       .res_type = RPMPD_LDOA,
+       .res_id = 3,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd mx_l12a_lvl_ao;
+static struct rpmpd mx_l12a_lvl = {
+       .pd = { .name = "mx", },
+       .peer = &mx_l12a_lvl_ao,
+       .res_type = RPMPD_LDOA,
+       .res_id = 12,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_l12a_lvl_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_l12a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_LDOA,
+       .res_id = 12,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_s2a_corner_ao;
+static struct rpmpd mx_s2a_corner = {
+       .pd = { .name = "mx", },
+       .peer = &mx_s2a_corner_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd mx_s2a_corner_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_s2a_corner,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd mx_rwmx0_lvl_ao;
+static struct rpmpd mx_rwmx0_lvl = {
+       .pd = { .name = "mx", },
+       .peer = &mx_rwmx0_lvl_ao,
+       .res_type = RPMPD_RWMX,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_rwmx0_lvl_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_rwmx0_lvl,
+       .active_only = true,
+       .res_type = RPMPD_RWMX,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_s6a_lvl_ao;
+static struct rpmpd mx_s6a_lvl = {
+       .pd = { .name = "mx", },
+       .peer = &mx_s6a_lvl_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 6,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_s6a_lvl_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_s6a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 6,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_s7a_lvl_ao;
+static struct rpmpd mx_s7a_lvl = {
+       .pd = { .name = "mx", },
+       .peer = &mx_s7a_lvl_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 7,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_s7a_lvl_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_s7a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 7,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_l12a_vfl = {
+       .pd = { .name = "mx_vfl", },
+       .res_type = RPMPD_LDOA,
+       .res_id = 12,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd mx_rwmx0_vfl = {
+       .pd = { .name = "mx_vfl", },
+       .res_type = RPMPD_RWMX,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd mx_rwsm6_vfl = {
+       .pd = { .name = "mx_vfl", },
+       .res_type = RPMPD_RWSM,
+       .res_id = 6,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+/* MD */
+static struct rpmpd md_s1a_corner_ao;
+static struct rpmpd md_s1a_corner = {
+       .pd = { .name = "md", },
+       .peer = &md_s1a_corner_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd md_s1a_corner_ao = {
+       .pd = { .name = "md_ao", },
+       .peer = &md_s1a_corner,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd md_s1a_lvl_ao;
+static struct rpmpd md_s1a_lvl = {
+       .pd = { .name = "md", },
+       .peer = &md_s1a_lvl_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd md_s1a_lvl_ao = {
+       .pd = { .name = "md_ao", },
+       .peer = &md_s1a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd md_s1a_vfc = {
+       .pd = { .name = "md_vfc", },
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_FLOOR_CORNER,
+};
+
+/* LPI_CX */
+static struct rpmpd lpi_cx_rwlc0_lvl = {
+       .pd = { .name = "lpi_cx", },
+       .res_type = RPMPD_RWLC,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd lpi_cx_rwlc0_vfl = {
+       .pd = { .name = "lpi_cx_vfl", },
+       .res_type = RPMPD_RWLC,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+/* LPI_MX */
+static struct rpmpd lpi_mx_rwlm0_lvl = {
+       .pd = { .name = "lpi_mx", },
+       .res_type = RPMPD_RWLM,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd lpi_mx_rwlm0_vfl = {
+       .pd = { .name = "lpi_mx_vfl", },
+       .res_type = RPMPD_RWLM,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+/* SSC_CX */
+static struct rpmpd ssc_cx_l26a_corner = {
+       .pd = { .name = "ssc_cx", },
+       .res_type = RPMPD_LDOA,
+       .res_id = 26,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd ssc_cx_rwlc0_lvl = {
+       .pd = { .name = "ssc_cx", },
+       .res_type = RPMPD_RWLC,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd ssc_cx_rwsc0_lvl = {
+       .pd = { .name = "ssc_cx", },
+       .res_type = RPMPD_RWSC,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd ssc_cx_l26a_vfc = {
+       .pd = { .name = "ssc_cx_vfc", },
+       .res_type = RPMPD_LDOA,
+       .res_id = 26,
+       .key = KEY_FLOOR_CORNER,
+};
+
+static struct rpmpd ssc_cx_rwlc0_vfl = {
+       .pd = { .name = "ssc_cx_vfl", },
+       .res_type = RPMPD_RWLC,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd ssc_cx_rwsc0_vfl = {
+       .pd = { .name = "ssc_cx_vfl", },
+       .res_type = RPMPD_RWSC,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+/* SSC_MX */
+static struct rpmpd ssc_mx_rwlm0_lvl = {
+       .pd = { .name = "ssc_mx", },
+       .res_type = RPMPD_RWLM,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd ssc_mx_rwsm0_lvl = {
+       .pd = { .name = "ssc_mx", },
+       .res_type = RPMPD_RWSM,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd ssc_mx_rwlm0_vfl = {
+       .pd = { .name = "ssc_mx_vfl", },
+       .res_type = RPMPD_RWLM,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd ssc_mx_rwsm0_vfl = {
+       .pd = { .name = "ssc_mx_vfl", },
+       .res_type = RPMPD_RWSM,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd *mdm9607_rpmpds[] = {
+       [MDM9607_VDDCX] =       &cx_s3a_lvl,
+       [MDM9607_VDDCX_AO] =    &cx_s3a_lvl_ao,
+       [MDM9607_VDDCX_VFL] =   &cx_s3a_vfl,
+       [MDM9607_VDDMX] =       &mx_l12a_lvl,
+       [MDM9607_VDDMX_AO] =    &mx_l12a_lvl_ao,
+       [MDM9607_VDDMX_VFL] =   &mx_l12a_vfl,
+};
+
+static const struct rpmpd_desc mdm9607_desc = {
+       .rpmpds = mdm9607_rpmpds,
+       .num_pds = ARRAY_SIZE(mdm9607_rpmpds),
+       .max_state = RPM_SMD_LEVEL_TURBO,
+};
+
+static struct rpmpd *msm8226_rpmpds[] = {
+       [MSM8226_VDDCX] =       &cx_s1a_corner,
+       [MSM8226_VDDCX_AO] =    &cx_s1a_corner_ao,
+       [MSM8226_VDDCX_VFC] =   &cx_s1a_vfc,
+};
+
+static const struct rpmpd_desc msm8226_desc = {
+       .rpmpds = msm8226_rpmpds,
+       .num_pds = ARRAY_SIZE(msm8226_rpmpds),
+       .max_state = MAX_CORNER_RPMPD_STATE,
+};
+
+static struct rpmpd *msm8939_rpmpds[] = {
+       [MSM8939_VDDMDCX] =     &md_s1a_corner,
+       [MSM8939_VDDMDCX_AO] =  &md_s1a_corner_ao,
+       [MSM8939_VDDMDCX_VFC] = &md_s1a_vfc,
+       [MSM8939_VDDCX] =       &cx_s2a_corner,
+       [MSM8939_VDDCX_AO] =    &cx_s2a_corner_ao,
+       [MSM8939_VDDCX_VFC] =   &cx_s2a_vfc,
+       [MSM8939_VDDMX] =       &mx_l3a_corner,
+       [MSM8939_VDDMX_AO] =    &mx_l3a_corner_ao,
+};
+
+static const struct rpmpd_desc msm8939_desc = {
+       .rpmpds = msm8939_rpmpds,
+       .num_pds = ARRAY_SIZE(msm8939_rpmpds),
+       .max_state = MAX_CORNER_RPMPD_STATE,
+};
+
+static struct rpmpd *msm8916_rpmpds[] = {
+       [MSM8916_VDDCX] =       &cx_s1a_corner,
+       [MSM8916_VDDCX_AO] =    &cx_s1a_corner_ao,
+       [MSM8916_VDDCX_VFC] =   &cx_s1a_vfc,
+       [MSM8916_VDDMX] =       &mx_l3a_corner,
+       [MSM8916_VDDMX_AO] =    &mx_l3a_corner_ao,
+};
+
+static const struct rpmpd_desc msm8916_desc = {
+       .rpmpds = msm8916_rpmpds,
+       .num_pds = ARRAY_SIZE(msm8916_rpmpds),
+       .max_state = MAX_CORNER_RPMPD_STATE,
+};
+
+static struct rpmpd *msm8953_rpmpds[] = {
+       [MSM8953_VDDMD] =       &md_s1a_lvl,
+       [MSM8953_VDDMD_AO] =    &md_s1a_lvl_ao,
+       [MSM8953_VDDCX] =       &cx_s2a_lvl,
+       [MSM8953_VDDCX_AO] =    &cx_s2a_lvl_ao,
+       [MSM8953_VDDCX_VFL] =   &cx_s2a_vfl,
+       [MSM8953_VDDMX] =       &mx_s7a_lvl,
+       [MSM8953_VDDMX_AO] =    &mx_s7a_lvl_ao,
+};
+
+static const struct rpmpd_desc msm8953_desc = {
+       .rpmpds = msm8953_rpmpds,
+       .num_pds = ARRAY_SIZE(msm8953_rpmpds),
+       .max_state = RPM_SMD_LEVEL_TURBO,
+};
+
+static struct rpmpd *msm8976_rpmpds[] = {
+       [MSM8976_VDDCX] =       &cx_s2a_lvl,
+       [MSM8976_VDDCX_AO] =    &cx_s2a_lvl_ao,
+       [MSM8976_VDDCX_VFL] =   &cx_rwsc2_vfl,
+       [MSM8976_VDDMX] =       &mx_s6a_lvl,
+       [MSM8976_VDDMX_AO] =    &mx_s6a_lvl_ao,
+       [MSM8976_VDDMX_VFL] =   &mx_rwsm6_vfl,
+};
+
+static const struct rpmpd_desc msm8976_desc = {
+       .rpmpds = msm8976_rpmpds,
+       .num_pds = ARRAY_SIZE(msm8976_rpmpds),
+       .max_state = RPM_SMD_LEVEL_TURBO_HIGH,
+};
+
+static struct rpmpd *msm8994_rpmpds[] = {
+       [MSM8994_VDDCX] =       &cx_s1a_corner,
+       [MSM8994_VDDCX_AO] =    &cx_s1a_corner_ao,
+       [MSM8994_VDDCX_VFC] =   &cx_s1a_vfc,
+       [MSM8994_VDDMX] =       &mx_s2a_corner,
+       [MSM8994_VDDMX_AO] =    &mx_s2a_corner_ao,
+
+       /* Attention! *Some* 8994 boards with pm8004 may use SMPC here! */
+       [MSM8994_VDDGFX] =      &gfx_s2b_corner,
+       [MSM8994_VDDGFX_VFC] =  &gfx_s2b_vfc,
+};
+
+static const struct rpmpd_desc msm8994_desc = {
+       .rpmpds = msm8994_rpmpds,
+       .num_pds = ARRAY_SIZE(msm8994_rpmpds),
+       .max_state = MAX_CORNER_RPMPD_STATE,
+};
+
+static struct rpmpd *msm8996_rpmpds[] = {
+       [MSM8996_VDDCX] =       &cx_s1a_corner,
+       [MSM8996_VDDCX_AO] =    &cx_s1a_corner_ao,
+       [MSM8996_VDDCX_VFC] =   &cx_s1a_vfc,
+       [MSM8996_VDDMX] =       &mx_s2a_corner,
+       [MSM8996_VDDMX_AO] =    &mx_s2a_corner_ao,
+       [MSM8996_VDDSSCX] =     &ssc_cx_l26a_corner,
+       [MSM8996_VDDSSCX_VFC] = &ssc_cx_l26a_vfc,
+};
+
+static const struct rpmpd_desc msm8996_desc = {
+       .rpmpds = msm8996_rpmpds,
+       .num_pds = ARRAY_SIZE(msm8996_rpmpds),
+       .max_state = MAX_CORNER_RPMPD_STATE,
+};
+
+static struct rpmpd *msm8998_rpmpds[] = {
+       [MSM8998_VDDCX] =       &cx_rwcx0_lvl,
+       [MSM8998_VDDCX_AO] =    &cx_rwcx0_lvl_ao,
+       [MSM8998_VDDCX_VFL] =   &cx_rwcx0_vfl,
+       [MSM8998_VDDMX] =       &mx_rwmx0_lvl,
+       [MSM8998_VDDMX_AO] =    &mx_rwmx0_lvl_ao,
+       [MSM8998_VDDMX_VFL] =   &mx_rwmx0_vfl,
+       [MSM8998_SSCCX] =       &ssc_cx_rwsc0_lvl,
+       [MSM8998_SSCCX_VFL] =   &ssc_cx_rwsc0_vfl,
+       [MSM8998_SSCMX] =       &ssc_mx_rwsm0_lvl,
+       [MSM8998_SSCMX_VFL] =   &ssc_mx_rwsm0_vfl,
+};
+
+static const struct rpmpd_desc msm8998_desc = {
+       .rpmpds = msm8998_rpmpds,
+       .num_pds = ARRAY_SIZE(msm8998_rpmpds),
+       .max_state = RPM_SMD_LEVEL_BINNING,
+};
+
+static struct rpmpd *qcs404_rpmpds[] = {
+       [QCS404_VDDMX] =        &mx_rwmx0_lvl,
+       [QCS404_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
+       [QCS404_VDDMX_VFL] =    &mx_rwmx0_vfl,
+       [QCS404_LPICX] =        &lpi_cx_rwlc0_lvl,
+       [QCS404_LPICX_VFL] =    &lpi_cx_rwlc0_vfl,
+       [QCS404_LPIMX] =        &lpi_mx_rwlm0_lvl,
+       [QCS404_LPIMX_VFL] =    &lpi_mx_rwlm0_vfl,
+};
+
+static const struct rpmpd_desc qcs404_desc = {
+       .rpmpds = qcs404_rpmpds,
+       .num_pds = ARRAY_SIZE(qcs404_rpmpds),
+       .max_state = RPM_SMD_LEVEL_BINNING,
+};
+
+static struct rpmpd *sdm660_rpmpds[] = {
+       [SDM660_VDDCX] =        &cx_rwcx0_lvl,
+       [SDM660_VDDCX_AO] =     &cx_rwcx0_lvl_ao,
+       [SDM660_VDDCX_VFL] =    &cx_rwcx0_vfl,
+       [SDM660_VDDMX] =        &mx_rwmx0_lvl,
+       [SDM660_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
+       [SDM660_VDDMX_VFL] =    &mx_rwmx0_vfl,
+       [SDM660_SSCCX] =        &ssc_cx_rwlc0_lvl,
+       [SDM660_SSCCX_VFL] =    &ssc_cx_rwlc0_vfl,
+       [SDM660_SSCMX] =        &ssc_mx_rwlm0_lvl,
+       [SDM660_SSCMX_VFL] =    &ssc_mx_rwlm0_vfl,
+};
+
+static const struct rpmpd_desc sdm660_desc = {
+       .rpmpds = sdm660_rpmpds,
+       .num_pds = ARRAY_SIZE(sdm660_rpmpds),
+       .max_state = RPM_SMD_LEVEL_TURBO,
+};
+
+static struct rpmpd *sm6115_rpmpds[] = {
+       [SM6115_VDDCX] =        &cx_rwcx0_lvl,
+       [SM6115_VDDCX_AO] =     &cx_rwcx0_lvl_ao,
+       [SM6115_VDDCX_VFL] =    &cx_rwcx0_vfl,
+       [SM6115_VDDMX] =        &mx_rwmx0_lvl,
+       [SM6115_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
+       [SM6115_VDDMX_VFL] =    &mx_rwmx0_vfl,
+       [SM6115_VDD_LPI_CX] =   &lpi_cx_rwlc0_lvl,
+       [SM6115_VDD_LPI_MX] =   &lpi_mx_rwlm0_lvl,
+};
+
+static const struct rpmpd_desc sm6115_desc = {
+       .rpmpds = sm6115_rpmpds,
+       .num_pds = ARRAY_SIZE(sm6115_rpmpds),
+       .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
+};
+
+static struct rpmpd *sm6125_rpmpds[] = {
+       [SM6125_VDDCX] =        &cx_rwcx0_lvl,
+       [SM6125_VDDCX_AO] =     &cx_rwcx0_lvl_ao,
+       [SM6125_VDDCX_VFL] =    &cx_rwcx0_vfl,
+       [SM6125_VDDMX] =        &mx_rwmx0_lvl,
+       [SM6125_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
+       [SM6125_VDDMX_VFL] =    &mx_rwmx0_vfl,
+};
+
+static const struct rpmpd_desc sm6125_desc = {
+       .rpmpds = sm6125_rpmpds,
+       .num_pds = ARRAY_SIZE(sm6125_rpmpds),
+       .max_state = RPM_SMD_LEVEL_BINNING,
+};
+
+static struct rpmpd *sm6375_rpmpds[] = {
+       [SM6375_VDDCX] =        &cx_rwcx0_lvl,
+       [SM6375_VDDCX_AO] =     &cx_rwcx0_lvl_ao,
+       [SM6375_VDDCX_VFL] =    &cx_rwcx0_vfl,
+       [SM6375_VDDMX] =        &mx_rwmx0_lvl,
+       [SM6375_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
+       [SM6375_VDDMX_VFL] =    &mx_rwmx0_vfl,
+       [SM6375_VDDGX] =        &gx_rwgx0_lvl,
+       [SM6375_VDDGX_AO] =     &gx_rwgx0_lvl_ao,
+       [SM6375_VDD_LPI_CX] =   &lpi_cx_rwlc0_lvl,
+       [SM6375_VDD_LPI_MX] =   &lpi_mx_rwlm0_lvl,
+};
+
+static const struct rpmpd_desc sm6375_desc = {
+       .rpmpds = sm6375_rpmpds,
+       .num_pds = ARRAY_SIZE(sm6375_rpmpds),
+       .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
+};
+
+static struct rpmpd *qcm2290_rpmpds[] = {
+       [QCM2290_VDDCX] =       &cx_rwcx0_lvl,
+       [QCM2290_VDDCX_AO] =    &cx_rwcx0_lvl_ao,
+       [QCM2290_VDDCX_VFL] =   &cx_rwcx0_vfl,
+       [QCM2290_VDDMX] =       &mx_rwmx0_lvl,
+       [QCM2290_VDDMX_AO] =    &mx_rwmx0_lvl_ao,
+       [QCM2290_VDDMX_VFL] =   &mx_rwmx0_vfl,
+       [QCM2290_VDD_LPI_CX] =  &lpi_cx_rwlc0_lvl,
+       [QCM2290_VDD_LPI_MX] =  &lpi_mx_rwlm0_lvl,
+};
+
+static const struct rpmpd_desc qcm2290_desc = {
+       .rpmpds = qcm2290_rpmpds,
+       .num_pds = ARRAY_SIZE(qcm2290_rpmpds),
+       .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
+};
+
+static const struct of_device_id rpmpd_match_table[] = {
+       { .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc },
+       { .compatible = "qcom,msm8226-rpmpd", .data = &msm8226_desc },
+       { .compatible = "qcom,msm8909-rpmpd", .data = &msm8916_desc },
+       { .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
+       { .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc },
+       { .compatible = "qcom,msm8953-rpmpd", .data = &msm8953_desc },
+       { .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
+       { .compatible = "qcom,msm8994-rpmpd", .data = &msm8994_desc },
+       { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
+       { .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
+       { .compatible = "qcom,qcm2290-rpmpd", .data = &qcm2290_desc },
+       { .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc },
+       { .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc },
+       { .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc },
+       { .compatible = "qcom,sm6125-rpmpd", .data = &sm6125_desc },
+       { .compatible = "qcom,sm6375-rpmpd", .data = &sm6375_desc },
+       { }
+};
+MODULE_DEVICE_TABLE(of, rpmpd_match_table);
+
+static int rpmpd_send_enable(struct rpmpd *pd, bool enable)
+{
+       struct rpmpd_req req = {
+               .key = KEY_ENABLE,
+               .nbytes = cpu_to_le32(sizeof(u32)),
+               .value = cpu_to_le32(enable),
+       };
+
+       return qcom_rpm_smd_write(pd->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
+                                 pd->res_type, pd->res_id, &req, sizeof(req));
+}
+
+static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner)
+{
+       struct rpmpd_req req = {
+               .key = pd->key,
+               .nbytes = cpu_to_le32(sizeof(u32)),
+               .value = cpu_to_le32(corner),
+       };
+
+       return qcom_rpm_smd_write(pd->rpm, state, pd->res_type, pd->res_id,
+                                 &req, sizeof(req));
+};
+
+static void to_active_sleep(struct rpmpd *pd, unsigned int corner,
+                           unsigned int *active, unsigned int *sleep)
+{
+       *active = corner;
+
+       if (pd->active_only)
+               *sleep = 0;
+       else
+               *sleep = *active;
+}
+
+static int rpmpd_aggregate_corner(struct rpmpd *pd)
+{
+       int ret;
+       struct rpmpd *peer = pd->peer;
+       unsigned int active_corner, sleep_corner;
+       unsigned int this_active_corner = 0, this_sleep_corner = 0;
+       unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
+
+       /* Clamp to the highest corner/level if sync_state isn't done yet */
+       if (!pd->state_synced)
+               this_active_corner = this_sleep_corner = pd->max_state - 1;
+       else
+               to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner);
+
+       if (peer && peer->enabled)
+               to_active_sleep(peer, peer->corner, &peer_active_corner,
+                               &peer_sleep_corner);
+
+       active_corner = max(this_active_corner, peer_active_corner);
+
+       ret = rpmpd_send_corner(pd, QCOM_SMD_RPM_ACTIVE_STATE, active_corner);
+       if (ret)
+               return ret;
+
+       sleep_corner = max(this_sleep_corner, peer_sleep_corner);
+
+       return rpmpd_send_corner(pd, QCOM_SMD_RPM_SLEEP_STATE, sleep_corner);
+}
+
+static int rpmpd_power_on(struct generic_pm_domain *domain)
+{
+       int ret;
+       struct rpmpd *pd = domain_to_rpmpd(domain);
+
+       mutex_lock(&rpmpd_lock);
+
+       ret = rpmpd_send_enable(pd, true);
+       if (ret)
+               goto out;
+
+       pd->enabled = true;
+
+       if (pd->corner)
+               ret = rpmpd_aggregate_corner(pd);
+
+out:
+       mutex_unlock(&rpmpd_lock);
+
+       return ret;
+}
+
+static int rpmpd_power_off(struct generic_pm_domain *domain)
+{
+       int ret;
+       struct rpmpd *pd = domain_to_rpmpd(domain);
+
+       mutex_lock(&rpmpd_lock);
+
+       ret = rpmpd_send_enable(pd, false);
+       if (!ret)
+               pd->enabled = false;
+
+       mutex_unlock(&rpmpd_lock);
+
+       return ret;
+}
+
+static int rpmpd_set_performance(struct generic_pm_domain *domain,
+                                unsigned int state)
+{
+       int ret = 0;
+       struct rpmpd *pd = domain_to_rpmpd(domain);
+
+       if (state > pd->max_state)
+               state = pd->max_state;
+
+       mutex_lock(&rpmpd_lock);
+
+       pd->corner = state;
+
+       /* Always send updates for vfc and vfl */
+       if (!pd->enabled && pd->key != cpu_to_le32(KEY_FLOOR_CORNER) &&
+           pd->key != cpu_to_le32(KEY_FLOOR_LEVEL))
+               goto out;
+
+       ret = rpmpd_aggregate_corner(pd);
+
+out:
+       mutex_unlock(&rpmpd_lock);
+
+       return ret;
+}
+
+static unsigned int rpmpd_get_performance(struct generic_pm_domain *genpd,
+                                         struct dev_pm_opp *opp)
+{
+       return dev_pm_opp_get_level(opp);
+}
+
+static int rpmpd_probe(struct platform_device *pdev)
+{
+       int i;
+       size_t num;
+       struct genpd_onecell_data *data;
+       struct qcom_smd_rpm *rpm;
+       struct rpmpd **rpmpds;
+       const struct rpmpd_desc *desc;
+
+       rpm = dev_get_drvdata(pdev->dev.parent);
+       if (!rpm) {
+               dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
+               return -ENODEV;
+       }
+
+       desc = of_device_get_match_data(&pdev->dev);
+       if (!desc)
+               return -EINVAL;
+
+       rpmpds = desc->rpmpds;
+       num = desc->num_pds;
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains),
+                                    GFP_KERNEL);
+       if (!data->domains)
+               return -ENOMEM;
+
+       data->num_domains = num;
+
+       for (i = 0; i < num; i++) {
+               if (!rpmpds[i]) {
+                       dev_warn(&pdev->dev, "rpmpds[] with empty entry at index=%d\n",
+                                i);
+                       continue;
+               }
+
+               rpmpds[i]->rpm = rpm;
+               rpmpds[i]->max_state = desc->max_state;
+               rpmpds[i]->pd.power_off = rpmpd_power_off;
+               rpmpds[i]->pd.power_on = rpmpd_power_on;
+               rpmpds[i]->pd.set_performance_state = rpmpd_set_performance;
+               rpmpds[i]->pd.opp_to_performance_state = rpmpd_get_performance;
+               pm_genpd_init(&rpmpds[i]->pd, NULL, true);
+
+               data->domains[i] = &rpmpds[i]->pd;
+       }
+
+       /* Add subdomains */
+       for (i = 0; i < num; i++) {
+               if (!rpmpds[i])
+                       continue;
+
+               if (rpmpds[i]->parent)
+                       pm_genpd_add_subdomain(rpmpds[i]->parent, &rpmpds[i]->pd);
+       }
+
+       return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
+}
+
+static void rpmpd_sync_state(struct device *dev)
+{
+       const struct rpmpd_desc *desc = of_device_get_match_data(dev);
+       struct rpmpd **rpmpds = desc->rpmpds;
+       struct rpmpd *pd;
+       unsigned int i;
+       int ret;
+
+       mutex_lock(&rpmpd_lock);
+       for (i = 0; i < desc->num_pds; i++) {
+               pd = rpmpds[i];
+               if (!pd)
+                       continue;
+
+               pd->state_synced = true;
+
+               if (!pd->enabled)
+                       pd->corner = 0;
+
+               ret = rpmpd_aggregate_corner(pd);
+               if (ret)
+                       dev_err(dev, "failed to sync %s: %d\n", pd->pd.name, ret);
+       }
+       mutex_unlock(&rpmpd_lock);
+}
+
+static struct platform_driver rpmpd_driver = {
+       .driver = {
+               .name = "qcom-rpmpd",
+               .of_match_table = rpmpd_match_table,
+               .suppress_bind_attrs = true,
+               .sync_state = rpmpd_sync_state,
+       },
+       .probe = rpmpd_probe,
+};
+
+static int __init rpmpd_init(void)
+{
+       return platform_driver_register(&rpmpd_driver);
+}
+core_initcall(rpmpd_init);
+
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPM Power Domain Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pmdomain/renesas/Makefile b/drivers/pmdomain/renesas/Makefile
new file mode 100644 (file)
index 0000000..e306e39
--- /dev/null
@@ -0,0 +1,30 @@
+# SPDX-License-Identifier: GPL-2.0
+# SoC
+obj-$(CONFIG_SYSC_R8A7742)     += r8a7742-sysc.o
+obj-$(CONFIG_SYSC_R8A7743)     += r8a7743-sysc.o
+obj-$(CONFIG_SYSC_R8A7745)     += r8a7745-sysc.o
+obj-$(CONFIG_SYSC_R8A77470)    += r8a77470-sysc.o
+obj-$(CONFIG_SYSC_R8A774A1)    += r8a774a1-sysc.o
+obj-$(CONFIG_SYSC_R8A774B1)    += r8a774b1-sysc.o
+obj-$(CONFIG_SYSC_R8A774C0)    += r8a774c0-sysc.o
+obj-$(CONFIG_SYSC_R8A774E1)    += r8a774e1-sysc.o
+obj-$(CONFIG_SYSC_R8A7779)     += r8a7779-sysc.o
+obj-$(CONFIG_SYSC_R8A7790)     += r8a7790-sysc.o
+obj-$(CONFIG_SYSC_R8A7791)     += r8a7791-sysc.o
+obj-$(CONFIG_SYSC_R8A7792)     += r8a7792-sysc.o
+obj-$(CONFIG_SYSC_R8A7794)     += r8a7794-sysc.o
+obj-$(CONFIG_SYSC_R8A7795)     += r8a7795-sysc.o
+obj-$(CONFIG_SYSC_R8A77960)    += r8a7796-sysc.o
+obj-$(CONFIG_SYSC_R8A77961)    += r8a7796-sysc.o
+obj-$(CONFIG_SYSC_R8A77965)    += r8a77965-sysc.o
+obj-$(CONFIG_SYSC_R8A77970)    += r8a77970-sysc.o
+obj-$(CONFIG_SYSC_R8A77980)    += r8a77980-sysc.o
+obj-$(CONFIG_SYSC_R8A77990)    += r8a77990-sysc.o
+obj-$(CONFIG_SYSC_R8A77995)    += r8a77995-sysc.o
+obj-$(CONFIG_SYSC_R8A779A0)    += r8a779a0-sysc.o
+obj-$(CONFIG_SYSC_R8A779F0)    += r8a779f0-sysc.o
+obj-$(CONFIG_SYSC_R8A779G0)    += r8a779g0-sysc.o
+# Family
+obj-$(CONFIG_SYSC_RCAR)                += rcar-sysc.o
+obj-$(CONFIG_SYSC_RCAR_GEN4)   += rcar-gen4-sysc.o
+obj-$(CONFIG_SYSC_RMOBILE)     += rmobile-sysc.o
diff --git a/drivers/pmdomain/renesas/r8a7742-sysc.c b/drivers/pmdomain/renesas/r8a7742-sysc.c
new file mode 100644 (file)
index 0000000..219a675
--- /dev/null
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G1H System Controller
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ */
+
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a7742-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a7742_areas[] __initconst = {
+       { "always-on",      0, 0, R8A7742_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca15-scu",   0x180, 0, R8A7742_PD_CA15_SCU,  R8A7742_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca15-cpu0",   0x40, 0, R8A7742_PD_CA15_CPU0, R8A7742_PD_CA15_SCU,
+         PD_CPU_NOCR },
+       { "ca15-cpu1",   0x40, 1, R8A7742_PD_CA15_CPU1, R8A7742_PD_CA15_SCU,
+         PD_CPU_NOCR },
+       { "ca15-cpu2",   0x40, 2, R8A7742_PD_CA15_CPU2, R8A7742_PD_CA15_SCU,
+         PD_CPU_NOCR },
+       { "ca15-cpu3",   0x40, 3, R8A7742_PD_CA15_CPU3, R8A7742_PD_CA15_SCU,
+         PD_CPU_NOCR },
+       { "ca7-scu",    0x100, 0, R8A7742_PD_CA7_SCU,   R8A7742_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca7-cpu0",   0x1c0, 0, R8A7742_PD_CA7_CPU0,  R8A7742_PD_CA7_SCU,
+         PD_CPU_NOCR },
+       { "ca7-cpu1",   0x1c0, 1, R8A7742_PD_CA7_CPU1,  R8A7742_PD_CA7_SCU,
+         PD_CPU_NOCR },
+       { "ca7-cpu2",   0x1c0, 2, R8A7742_PD_CA7_CPU2,  R8A7742_PD_CA7_SCU,
+         PD_CPU_NOCR },
+       { "ca7-cpu3",   0x1c0, 3, R8A7742_PD_CA7_CPU3,  R8A7742_PD_CA7_SCU,
+         PD_CPU_NOCR },
+       { "rgx",         0xc0, 0, R8A7742_PD_RGX,       R8A7742_PD_ALWAYS_ON },
+};
+
+const struct rcar_sysc_info r8a7742_sysc_info __initconst = {
+       .areas = r8a7742_areas,
+       .num_areas = ARRAY_SIZE(r8a7742_areas),
+};
diff --git a/drivers/pmdomain/renesas/r8a7743-sysc.c b/drivers/pmdomain/renesas/r8a7743-sysc.c
new file mode 100644 (file)
index 0000000..4e2c0ab
--- /dev/null
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G1M System Controller
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ */
+
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a7743-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a7743_areas[] __initconst = {
+       { "always-on",      0, 0, R8A7743_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca15-scu",   0x180, 0, R8A7743_PD_CA15_SCU,  R8A7743_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca15-cpu0",   0x40, 0, R8A7743_PD_CA15_CPU0, R8A7743_PD_CA15_SCU,
+         PD_CPU_NOCR },
+       { "ca15-cpu1",   0x40, 1, R8A7743_PD_CA15_CPU1, R8A7743_PD_CA15_SCU,
+         PD_CPU_NOCR },
+       { "sgx",         0xc0, 0, R8A7743_PD_SGX,       R8A7743_PD_ALWAYS_ON },
+};
+
+const struct rcar_sysc_info r8a7743_sysc_info __initconst = {
+       .areas = r8a7743_areas,
+       .num_areas = ARRAY_SIZE(r8a7743_areas),
+};
diff --git a/drivers/pmdomain/renesas/r8a7745-sysc.c b/drivers/pmdomain/renesas/r8a7745-sysc.c
new file mode 100644 (file)
index 0000000..865821a
--- /dev/null
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G1E System Controller
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ */
+
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a7745-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a7745_areas[] __initconst = {
+       { "always-on",      0, 0, R8A7745_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca7-scu",    0x100, 0, R8A7745_PD_CA7_SCU,   R8A7745_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca7-cpu0",   0x1c0, 0, R8A7745_PD_CA7_CPU0,  R8A7745_PD_CA7_SCU,
+         PD_CPU_NOCR },
+       { "ca7-cpu1",   0x1c0, 1, R8A7745_PD_CA7_CPU1,  R8A7745_PD_CA7_SCU,
+         PD_CPU_NOCR },
+       { "sgx",         0xc0, 0, R8A7745_PD_SGX,       R8A7745_PD_ALWAYS_ON },
+};
+
+const struct rcar_sysc_info r8a7745_sysc_info __initconst = {
+       .areas = r8a7745_areas,
+       .num_areas = ARRAY_SIZE(r8a7745_areas),
+};
diff --git a/drivers/pmdomain/renesas/r8a77470-sysc.c b/drivers/pmdomain/renesas/r8a77470-sysc.c
new file mode 100644 (file)
index 0000000..1eeb801
--- /dev/null
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G1C System Controller
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ */
+
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a77470-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a77470_areas[] __initconst = {
+       { "always-on",      0, 0, R8A77470_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca7-scu",    0x100, 0, R8A77470_PD_CA7_SCU,  R8A77470_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca7-cpu0",   0x1c0, 0, R8A77470_PD_CA7_CPU0, R8A77470_PD_CA7_SCU,
+         PD_CPU_NOCR },
+       { "ca7-cpu1",   0x1c0, 1, R8A77470_PD_CA7_CPU1, R8A77470_PD_CA7_SCU,
+         PD_CPU_NOCR },
+       { "sgx",         0xc0, 0, R8A77470_PD_SGX, R8A77470_PD_ALWAYS_ON },
+};
+
+const struct rcar_sysc_info r8a77470_sysc_info __initconst = {
+       .areas = r8a77470_areas,
+       .num_areas = ARRAY_SIZE(r8a77470_areas),
+};
diff --git a/drivers/pmdomain/renesas/r8a774a1-sysc.c b/drivers/pmdomain/renesas/r8a774a1-sysc.c
new file mode 100644 (file)
index 0000000..38ac2c6
--- /dev/null
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G2M System Controller
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ *
+ * Based on Renesas R-Car M3-W System Controller
+ * Copyright (C) 2016 Glider bvba
+ */
+
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a774a1-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a774a1_areas[] __initconst = {
+       { "always-on",      0, 0, R8A774A1_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca57-scu",   0x1c0, 0, R8A774A1_PD_CA57_SCU, R8A774A1_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca57-cpu0",   0x80, 0, R8A774A1_PD_CA57_CPU0, R8A774A1_PD_CA57_SCU,
+         PD_CPU_NOCR },
+       { "ca57-cpu1",   0x80, 1, R8A774A1_PD_CA57_CPU1, R8A774A1_PD_CA57_SCU,
+         PD_CPU_NOCR },
+       { "ca53-scu",   0x140, 0, R8A774A1_PD_CA53_SCU, R8A774A1_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca53-cpu0",  0x200, 0, R8A774A1_PD_CA53_CPU0, R8A774A1_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu1",  0x200, 1, R8A774A1_PD_CA53_CPU1, R8A774A1_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu2",  0x200, 2, R8A774A1_PD_CA53_CPU2, R8A774A1_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu3",  0x200, 3, R8A774A1_PD_CA53_CPU3, R8A774A1_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "a3vc",       0x380, 0, R8A774A1_PD_A3VC,     R8A774A1_PD_ALWAYS_ON },
+       { "a2vc0",      0x3c0, 0, R8A774A1_PD_A2VC0,    R8A774A1_PD_A3VC },
+       { "a2vc1",      0x3c0, 1, R8A774A1_PD_A2VC1,    R8A774A1_PD_A3VC },
+       { "3dg-a",      0x100, 0, R8A774A1_PD_3DG_A,    R8A774A1_PD_ALWAYS_ON },
+       { "3dg-b",      0x100, 1, R8A774A1_PD_3DG_B,    R8A774A1_PD_3DG_A },
+};
+
+const struct rcar_sysc_info r8a774a1_sysc_info __initconst = {
+       .areas = r8a774a1_areas,
+       .num_areas = ARRAY_SIZE(r8a774a1_areas),
+};
diff --git a/drivers/pmdomain/renesas/r8a774b1-sysc.c b/drivers/pmdomain/renesas/r8a774b1-sysc.c
new file mode 100644 (file)
index 0000000..5f97ff2
--- /dev/null
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G2N System Controller
+ * Copyright (C) 2019 Renesas Electronics Corp.
+ *
+ * Based on Renesas R-Car M3-W System Controller
+ * Copyright (C) 2016 Glider bvba
+ */
+
+#include <linux/bits.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a774b1-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a774b1_areas[] __initconst = {
+       { "always-on",      0, 0, R8A774B1_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca57-scu",   0x1c0, 0, R8A774B1_PD_CA57_SCU, R8A774B1_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca57-cpu0",   0x80, 0, R8A774B1_PD_CA57_CPU0, R8A774B1_PD_CA57_SCU,
+         PD_CPU_NOCR },
+       { "ca57-cpu1",   0x80, 1, R8A774B1_PD_CA57_CPU1, R8A774B1_PD_CA57_SCU,
+         PD_CPU_NOCR },
+       { "a3vc",       0x380, 0, R8A774B1_PD_A3VC,     R8A774B1_PD_ALWAYS_ON },
+       { "a3vp",       0x340, 0, R8A774B1_PD_A3VP,     R8A774B1_PD_ALWAYS_ON },
+       { "a2vc1",      0x3c0, 1, R8A774B1_PD_A2VC1,    R8A774B1_PD_A3VC },
+       { "3dg-a",      0x100, 0, R8A774B1_PD_3DG_A,    R8A774B1_PD_ALWAYS_ON },
+       { "3dg-b",      0x100, 1, R8A774B1_PD_3DG_B,    R8A774B1_PD_3DG_A },
+};
+
+const struct rcar_sysc_info r8a774b1_sysc_info __initconst = {
+       .areas = r8a774b1_areas,
+       .num_areas = ARRAY_SIZE(r8a774b1_areas),
+       .extmask_offs = 0x2f8,
+       .extmask_val = BIT(0),
+};
diff --git a/drivers/pmdomain/renesas/r8a774c0-sysc.c b/drivers/pmdomain/renesas/r8a774c0-sysc.c
new file mode 100644 (file)
index 0000000..c1c216f
--- /dev/null
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G2E System Controller
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ *
+ * Based on Renesas R-Car E3 System Controller
+ */
+
+#include <linux/bits.h>
+#include <linux/kernel.h>
+#include <linux/sys_soc.h>
+
+#include <dt-bindings/power/r8a774c0-sysc.h>
+
+#include "rcar-sysc.h"
+
+static struct rcar_sysc_area r8a774c0_areas[] __initdata = {
+       { "always-on",      0, 0, R8A774C0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca53-scu",   0x140, 0, R8A774C0_PD_CA53_SCU,  R8A774C0_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca53-cpu0",  0x200, 0, R8A774C0_PD_CA53_CPU0, R8A774C0_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu1",  0x200, 1, R8A774C0_PD_CA53_CPU1, R8A774C0_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "a3vc",       0x380, 0, R8A774C0_PD_A3VC,     R8A774C0_PD_ALWAYS_ON },
+       { "a2vc1",      0x3c0, 1, R8A774C0_PD_A2VC1,    R8A774C0_PD_A3VC },
+       { "3dg-a",      0x100, 0, R8A774C0_PD_3DG_A,    R8A774C0_PD_ALWAYS_ON },
+       { "3dg-b",      0x100, 1, R8A774C0_PD_3DG_B,    R8A774C0_PD_3DG_A },
+};
+
+/* Fixups for RZ/G2E ES1.0 revision */
+static const struct soc_device_attribute r8a774c0[] __initconst = {
+       { .soc_id = "r8a774c0", .revision = "ES1.0" },
+       { /* sentinel */ }
+};
+
+static int __init r8a774c0_sysc_init(void)
+{
+       if (soc_device_match(r8a774c0)) {
+               /* Fix incorrect 3DG hierarchy */
+               swap(r8a774c0_areas[6], r8a774c0_areas[7]);
+               r8a774c0_areas[6].parent = R8A774C0_PD_ALWAYS_ON;
+               r8a774c0_areas[7].parent = R8A774C0_PD_3DG_B;
+       }
+
+       return 0;
+}
+
+const struct rcar_sysc_info r8a774c0_sysc_info __initconst = {
+       .init = r8a774c0_sysc_init,
+       .areas = r8a774c0_areas,
+       .num_areas = ARRAY_SIZE(r8a774c0_areas),
+       .extmask_offs = 0x2f8,
+       .extmask_val = BIT(0),
+};
diff --git a/drivers/pmdomain/renesas/r8a774e1-sysc.c b/drivers/pmdomain/renesas/r8a774e1-sysc.c
new file mode 100644 (file)
index 0000000..18449f7
--- /dev/null
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G2H System Controller
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ *
+ * Based on Renesas R-Car H3 System Controller
+ * Copyright (C) 2016-2017 Glider bvba
+ */
+
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a774e1-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a774e1_areas[] __initconst = {
+       { "always-on",      0, 0, R8A774E1_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca57-scu",   0x1c0, 0, R8A774E1_PD_CA57_SCU, R8A774E1_PD_ALWAYS_ON, PD_SCU },
+       { "ca57-cpu0",   0x80, 0, R8A774E1_PD_CA57_CPU0, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR },
+       { "ca57-cpu1",   0x80, 1, R8A774E1_PD_CA57_CPU1, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR },
+       { "ca57-cpu2",   0x80, 2, R8A774E1_PD_CA57_CPU2, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR },
+       { "ca57-cpu3",   0x80, 3, R8A774E1_PD_CA57_CPU3, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR },
+       { "ca53-scu",   0x140, 0, R8A774E1_PD_CA53_SCU, R8A774E1_PD_ALWAYS_ON, PD_SCU },
+       { "ca53-cpu0",  0x200, 0, R8A774E1_PD_CA53_CPU0, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR },
+       { "ca53-cpu1",  0x200, 1, R8A774E1_PD_CA53_CPU1, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR },
+       { "ca53-cpu2",  0x200, 2, R8A774E1_PD_CA53_CPU2, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR },
+       { "ca53-cpu3",  0x200, 3, R8A774E1_PD_CA53_CPU3, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR },
+       { "a3vp",       0x340, 0, R8A774E1_PD_A3VP, R8A774E1_PD_ALWAYS_ON },
+       { "a3vc",       0x380, 0, R8A774E1_PD_A3VC, R8A774E1_PD_ALWAYS_ON },
+       { "a2vc1",      0x3c0, 1, R8A774E1_PD_A2VC1, R8A774E1_PD_A3VC },
+       { "3dg-a",      0x100, 0, R8A774E1_PD_3DG_A, R8A774E1_PD_ALWAYS_ON },
+       { "3dg-b",      0x100, 1, R8A774E1_PD_3DG_B, R8A774E1_PD_3DG_A },
+       { "3dg-c",      0x100, 2, R8A774E1_PD_3DG_C, R8A774E1_PD_3DG_B },
+       { "3dg-d",      0x100, 3, R8A774E1_PD_3DG_D, R8A774E1_PD_3DG_C },
+       { "3dg-e",      0x100, 4, R8A774E1_PD_3DG_E, R8A774E1_PD_3DG_D },
+};
+
+const struct rcar_sysc_info r8a774e1_sysc_info __initconst = {
+       .areas = r8a774e1_areas,
+       .num_areas = ARRAY_SIZE(r8a774e1_areas),
+       .extmask_offs = 0x2f8,
+       .extmask_val = BIT(0),
+};
diff --git a/drivers/pmdomain/renesas/r8a7779-sysc.c b/drivers/pmdomain/renesas/r8a7779-sysc.c
new file mode 100644 (file)
index 0000000..e24a715
--- /dev/null
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car H1 System Controller
+ *
+ * Copyright (C) 2016 Glider bvba
+ */
+
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a7779-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a7779_areas[] __initconst = {
+       { "always-on",      0, 0, R8A7779_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "arm1",        0x40, 1, R8A7779_PD_ARM1,      R8A7779_PD_ALWAYS_ON,
+         PD_CPU_CR },
+       { "arm2",        0x40, 2, R8A7779_PD_ARM2,      R8A7779_PD_ALWAYS_ON,
+         PD_CPU_CR },
+       { "arm3",        0x40, 3, R8A7779_PD_ARM3,      R8A7779_PD_ALWAYS_ON,
+         PD_CPU_CR },
+       { "sgx",         0xc0, 0, R8A7779_PD_SGX,       R8A7779_PD_ALWAYS_ON },
+       { "vdp",        0x100, 0, R8A7779_PD_VDP,       R8A7779_PD_ALWAYS_ON },
+       { "imp",        0x140, 0, R8A7779_PD_IMP,       R8A7779_PD_ALWAYS_ON },
+};
+
+const struct rcar_sysc_info r8a7779_sysc_info __initconst = {
+       .areas = r8a7779_areas,
+       .num_areas = ARRAY_SIZE(r8a7779_areas),
+};
diff --git a/drivers/pmdomain/renesas/r8a7790-sysc.c b/drivers/pmdomain/renesas/r8a7790-sysc.c
new file mode 100644 (file)
index 0000000..b9afe7f
--- /dev/null
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car H2 System Controller
+ *
+ * Copyright (C) 2016 Glider bvba
+ */
+
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a7790-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a7790_areas[] __initconst = {
+       { "always-on",      0, 0, R8A7790_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca15-scu",   0x180, 0, R8A7790_PD_CA15_SCU,  R8A7790_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca15-cpu0",   0x40, 0, R8A7790_PD_CA15_CPU0, R8A7790_PD_CA15_SCU,
+         PD_CPU_NOCR },
+       { "ca15-cpu1",   0x40, 1, R8A7790_PD_CA15_CPU1, R8A7790_PD_CA15_SCU,
+         PD_CPU_NOCR },
+       { "ca15-cpu2",   0x40, 2, R8A7790_PD_CA15_CPU2, R8A7790_PD_CA15_SCU,
+         PD_CPU_NOCR },
+       { "ca15-cpu3",   0x40, 3, R8A7790_PD_CA15_CPU3, R8A7790_PD_CA15_SCU,
+         PD_CPU_NOCR },
+       { "ca7-scu",    0x100, 0, R8A7790_PD_CA7_SCU,   R8A7790_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca7-cpu0",   0x1c0, 0, R8A7790_PD_CA7_CPU0,  R8A7790_PD_CA7_SCU,
+         PD_CPU_NOCR },
+       { "ca7-cpu1",   0x1c0, 1, R8A7790_PD_CA7_CPU1,  R8A7790_PD_CA7_SCU,
+         PD_CPU_NOCR },
+       { "ca7-cpu2",   0x1c0, 2, R8A7790_PD_CA7_CPU2,  R8A7790_PD_CA7_SCU,
+         PD_CPU_NOCR },
+       { "ca7-cpu3",   0x1c0, 3, R8A7790_PD_CA7_CPU3,  R8A7790_PD_CA7_SCU,
+         PD_CPU_NOCR },
+       { "sh-4a",       0x80, 0, R8A7790_PD_SH_4A,     R8A7790_PD_ALWAYS_ON },
+       { "rgx",         0xc0, 0, R8A7790_PD_RGX,       R8A7790_PD_ALWAYS_ON },
+       { "imp",        0x140, 0, R8A7790_PD_IMP,       R8A7790_PD_ALWAYS_ON },
+};
+
+const struct rcar_sysc_info r8a7790_sysc_info __initconst = {
+       .areas = r8a7790_areas,
+       .num_areas = ARRAY_SIZE(r8a7790_areas),
+};
diff --git a/drivers/pmdomain/renesas/r8a7791-sysc.c b/drivers/pmdomain/renesas/r8a7791-sysc.c
new file mode 100644 (file)
index 0000000..f00fa24
--- /dev/null
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car M2-W/N System Controller
+ *
+ * Copyright (C) 2016 Glider bvba
+ */
+
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a7791-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a7791_areas[] __initconst = {
+       { "always-on",      0, 0, R8A7791_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca15-scu",   0x180, 0, R8A7791_PD_CA15_SCU,  R8A7791_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca15-cpu0",   0x40, 0, R8A7791_PD_CA15_CPU0, R8A7791_PD_CA15_SCU,
+         PD_CPU_NOCR },
+       { "ca15-cpu1",   0x40, 1, R8A7791_PD_CA15_CPU1, R8A7791_PD_CA15_SCU,
+         PD_CPU_NOCR },
+       { "sh-4a",       0x80, 0, R8A7791_PD_SH_4A,     R8A7791_PD_ALWAYS_ON },
+       { "sgx",         0xc0, 0, R8A7791_PD_SGX,       R8A7791_PD_ALWAYS_ON },
+};
+
+const struct rcar_sysc_info r8a7791_sysc_info __initconst = {
+       .areas = r8a7791_areas,
+       .num_areas = ARRAY_SIZE(r8a7791_areas),
+};
diff --git a/drivers/pmdomain/renesas/r8a7792-sysc.c b/drivers/pmdomain/renesas/r8a7792-sysc.c
new file mode 100644 (file)
index 0000000..60aae24
--- /dev/null
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car V2H (R8A7792) System Controller
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a7792-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a7792_areas[] __initconst = {
+       { "always-on",      0, 0, R8A7792_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca15-scu",   0x180, 0, R8A7792_PD_CA15_SCU,  R8A7792_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca15-cpu0",   0x40, 0, R8A7792_PD_CA15_CPU0, R8A7792_PD_CA15_SCU,
+         PD_CPU_NOCR },
+       { "ca15-cpu1",   0x40, 1, R8A7792_PD_CA15_CPU1, R8A7792_PD_CA15_SCU,
+         PD_CPU_NOCR },
+       { "sgx",         0xc0, 0, R8A7792_PD_SGX,       R8A7792_PD_ALWAYS_ON },
+       { "imp",        0x140, 0, R8A7792_PD_IMP,       R8A7792_PD_ALWAYS_ON },
+};
+
+const struct rcar_sysc_info r8a7792_sysc_info __initconst = {
+       .areas = r8a7792_areas,
+       .num_areas = ARRAY_SIZE(r8a7792_areas),
+};
diff --git a/drivers/pmdomain/renesas/r8a7794-sysc.c b/drivers/pmdomain/renesas/r8a7794-sysc.c
new file mode 100644 (file)
index 0000000..72ef4e8
--- /dev/null
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car E2 System Controller
+ *
+ * Copyright (C) 2016 Glider bvba
+ */
+
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a7794-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a7794_areas[] __initconst = {
+       { "always-on",      0, 0, R8A7794_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca7-scu",    0x100, 0, R8A7794_PD_CA7_SCU,   R8A7794_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca7-cpu0",   0x1c0, 0, R8A7794_PD_CA7_CPU0,  R8A7794_PD_CA7_SCU,
+         PD_CPU_NOCR },
+       { "ca7-cpu1",   0x1c0, 1, R8A7794_PD_CA7_CPU1,  R8A7794_PD_CA7_SCU,
+         PD_CPU_NOCR },
+       { "sh-4a",       0x80, 0, R8A7794_PD_SH_4A,     R8A7794_PD_ALWAYS_ON },
+       { "sgx",         0xc0, 0, R8A7794_PD_SGX,       R8A7794_PD_ALWAYS_ON },
+};
+
+const struct rcar_sysc_info r8a7794_sysc_info __initconst = {
+       .areas = r8a7794_areas,
+       .num_areas = ARRAY_SIZE(r8a7794_areas),
+};
diff --git a/drivers/pmdomain/renesas/r8a7795-sysc.c b/drivers/pmdomain/renesas/r8a7795-sysc.c
new file mode 100644 (file)
index 0000000..cbe1ff0
--- /dev/null
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car H3 System Controller
+ *
+ * Copyright (C) 2016-2017 Glider bvba
+ */
+
+#include <linux/bits.h>
+#include <linux/kernel.h>
+#include <linux/sys_soc.h>
+
+#include <dt-bindings/power/r8a7795-sysc.h>
+
+#include "rcar-sysc.h"
+
+static struct rcar_sysc_area r8a7795_areas[] __initdata = {
+       { "always-on",      0, 0, R8A7795_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca57-scu",   0x1c0, 0, R8A7795_PD_CA57_SCU,  R8A7795_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca57-cpu0",   0x80, 0, R8A7795_PD_CA57_CPU0, R8A7795_PD_CA57_SCU,
+         PD_CPU_NOCR },
+       { "ca57-cpu1",   0x80, 1, R8A7795_PD_CA57_CPU1, R8A7795_PD_CA57_SCU,
+         PD_CPU_NOCR },
+       { "ca57-cpu2",   0x80, 2, R8A7795_PD_CA57_CPU2, R8A7795_PD_CA57_SCU,
+         PD_CPU_NOCR },
+       { "ca57-cpu3",   0x80, 3, R8A7795_PD_CA57_CPU3, R8A7795_PD_CA57_SCU,
+         PD_CPU_NOCR },
+       { "ca53-scu",   0x140, 0, R8A7795_PD_CA53_SCU,  R8A7795_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca53-cpu0",  0x200, 0, R8A7795_PD_CA53_CPU0, R8A7795_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu1",  0x200, 1, R8A7795_PD_CA53_CPU1, R8A7795_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu2",  0x200, 2, R8A7795_PD_CA53_CPU2, R8A7795_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu3",  0x200, 3, R8A7795_PD_CA53_CPU3, R8A7795_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "a3vp",       0x340, 0, R8A7795_PD_A3VP,      R8A7795_PD_ALWAYS_ON },
+       { "cr7",        0x240, 0, R8A7795_PD_CR7,       R8A7795_PD_ALWAYS_ON },
+       { "a3vc",       0x380, 0, R8A7795_PD_A3VC,      R8A7795_PD_ALWAYS_ON },
+       { "a2vc1",      0x3c0, 1, R8A7795_PD_A2VC1,     R8A7795_PD_A3VC },
+       { "3dg-a",      0x100, 0, R8A7795_PD_3DG_A,     R8A7795_PD_ALWAYS_ON },
+       { "3dg-b",      0x100, 1, R8A7795_PD_3DG_B,     R8A7795_PD_3DG_A },
+       { "3dg-c",      0x100, 2, R8A7795_PD_3DG_C,     R8A7795_PD_3DG_B },
+       { "3dg-d",      0x100, 3, R8A7795_PD_3DG_D,     R8A7795_PD_3DG_C },
+       { "3dg-e",      0x100, 4, R8A7795_PD_3DG_E,     R8A7795_PD_3DG_D },
+       { "a3ir",       0x180, 0, R8A7795_PD_A3IR,      R8A7795_PD_ALWAYS_ON },
+};
+
+
+       /*
+        * Fixups for R-Car H3 revisions
+        */
+
+#define NO_EXTMASK     BIT(1)          /* Missing SYSCEXTMASK register */
+
+static const struct soc_device_attribute r8a7795_quirks_match[] __initconst = {
+       {
+               .soc_id = "r8a7795", .revision = "ES2.*",
+               .data = (void *)(NO_EXTMASK),
+       },
+       { /* sentinel */ }
+};
+
+static int __init r8a7795_sysc_init(void)
+{
+       const struct soc_device_attribute *attr;
+       u32 quirks = 0;
+
+       attr = soc_device_match(r8a7795_quirks_match);
+       if (attr)
+               quirks = (uintptr_t)attr->data;
+
+       if (quirks & NO_EXTMASK)
+               r8a7795_sysc_info.extmask_val = 0;
+
+       return 0;
+}
+
+struct rcar_sysc_info r8a7795_sysc_info __initdata = {
+       .init = r8a7795_sysc_init,
+       .areas = r8a7795_areas,
+       .num_areas = ARRAY_SIZE(r8a7795_areas),
+       .extmask_offs = 0x2f8,
+       .extmask_val = BIT(0),
+};
diff --git a/drivers/pmdomain/renesas/r8a7796-sysc.c b/drivers/pmdomain/renesas/r8a7796-sysc.c
new file mode 100644 (file)
index 0000000..471bd5b
--- /dev/null
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car M3-W/W+ System Controller
+ *
+ * Copyright (C) 2016 Glider bvba
+ * Copyright (C) 2018-2019 Renesas Electronics Corporation
+ */
+
+#include <linux/bits.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a7796-sysc.h>
+
+#include "rcar-sysc.h"
+
+static struct rcar_sysc_area r8a7796_areas[] __initdata = {
+       { "always-on",      0, 0, R8A7796_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca57-scu",   0x1c0, 0, R8A7796_PD_CA57_SCU,  R8A7796_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca57-cpu0",   0x80, 0, R8A7796_PD_CA57_CPU0, R8A7796_PD_CA57_SCU,
+         PD_CPU_NOCR },
+       { "ca57-cpu1",   0x80, 1, R8A7796_PD_CA57_CPU1, R8A7796_PD_CA57_SCU,
+         PD_CPU_NOCR },
+       { "ca53-scu",   0x140, 0, R8A7796_PD_CA53_SCU,  R8A7796_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca53-cpu0",  0x200, 0, R8A7796_PD_CA53_CPU0, R8A7796_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu1",  0x200, 1, R8A7796_PD_CA53_CPU1, R8A7796_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu2",  0x200, 2, R8A7796_PD_CA53_CPU2, R8A7796_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu3",  0x200, 3, R8A7796_PD_CA53_CPU3, R8A7796_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "cr7",        0x240, 0, R8A7796_PD_CR7,       R8A7796_PD_ALWAYS_ON },
+       { "a3vc",       0x380, 0, R8A7796_PD_A3VC,      R8A7796_PD_ALWAYS_ON },
+       { "a2vc0",      0x3c0, 0, R8A7796_PD_A2VC0,     R8A7796_PD_A3VC },
+       { "a2vc1",      0x3c0, 1, R8A7796_PD_A2VC1,     R8A7796_PD_A3VC },
+       { "3dg-a",      0x100, 0, R8A7796_PD_3DG_A,     R8A7796_PD_ALWAYS_ON },
+       { "3dg-b",      0x100, 1, R8A7796_PD_3DG_B,     R8A7796_PD_3DG_A },
+       { "a3ir",       0x180, 0, R8A7796_PD_A3IR,      R8A7796_PD_ALWAYS_ON },
+};
+
+
+#ifdef CONFIG_SYSC_R8A77960
+const struct rcar_sysc_info r8a77960_sysc_info __initconst = {
+       .areas = r8a7796_areas,
+       .num_areas = ARRAY_SIZE(r8a7796_areas),
+};
+#endif /* CONFIG_SYSC_R8A77960 */
+
+#ifdef CONFIG_SYSC_R8A77961
+static int __init r8a77961_sysc_init(void)
+{
+       rcar_sysc_nullify(r8a7796_areas, ARRAY_SIZE(r8a7796_areas),
+                         R8A7796_PD_A2VC0);
+
+       return 0;
+}
+
+const struct rcar_sysc_info r8a77961_sysc_info __initconst = {
+       .init = r8a77961_sysc_init,
+       .areas = r8a7796_areas,
+       .num_areas = ARRAY_SIZE(r8a7796_areas),
+       .extmask_offs = 0x2f8,
+       .extmask_val = BIT(0),
+};
+#endif /* CONFIG_SYSC_R8A77961 */
diff --git a/drivers/pmdomain/renesas/r8a77965-sysc.c b/drivers/pmdomain/renesas/r8a77965-sysc.c
new file mode 100644 (file)
index 0000000..ff0b0d1
--- /dev/null
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car M3-N System Controller
+ * Copyright (C) 2018 Jacopo Mondi <jacopo+renesas@jmondi.org>
+ *
+ * Based on Renesas R-Car M3-W System Controller
+ * Copyright (C) 2016 Glider bvba
+ */
+
+#include <linux/bits.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a77965-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a77965_areas[] __initconst = {
+       { "always-on",      0, 0, R8A77965_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca57-scu",   0x1c0, 0, R8A77965_PD_CA57_SCU, R8A77965_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca57-cpu0",   0x80, 0, R8A77965_PD_CA57_CPU0, R8A77965_PD_CA57_SCU,
+         PD_CPU_NOCR },
+       { "ca57-cpu1",   0x80, 1, R8A77965_PD_CA57_CPU1, R8A77965_PD_CA57_SCU,
+         PD_CPU_NOCR },
+       { "cr7",        0x240, 0, R8A77965_PD_CR7,      R8A77965_PD_ALWAYS_ON },
+       { "a3vc",       0x380, 0, R8A77965_PD_A3VC,     R8A77965_PD_ALWAYS_ON },
+       { "a3vp",       0x340, 0, R8A77965_PD_A3VP,     R8A77965_PD_ALWAYS_ON },
+       { "a2vc1",      0x3c0, 1, R8A77965_PD_A2VC1,    R8A77965_PD_A3VC },
+       { "3dg-a",      0x100, 0, R8A77965_PD_3DG_A,    R8A77965_PD_ALWAYS_ON },
+       { "3dg-b",      0x100, 1, R8A77965_PD_3DG_B,    R8A77965_PD_3DG_A },
+};
+
+const struct rcar_sysc_info r8a77965_sysc_info __initconst = {
+       .areas = r8a77965_areas,
+       .num_areas = ARRAY_SIZE(r8a77965_areas),
+       .extmask_offs = 0x2f8,
+       .extmask_val = BIT(0),
+};
diff --git a/drivers/pmdomain/renesas/r8a77970-sysc.c b/drivers/pmdomain/renesas/r8a77970-sysc.c
new file mode 100644 (file)
index 0000000..7062582
--- /dev/null
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car V3M System Controller
+ *
+ * Copyright (C) 2017 Cogent Embedded Inc.
+ */
+
+#include <linux/bits.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a77970-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a77970_areas[] __initconst = {
+       { "always-on",      0, 0, R8A77970_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca53-scu",   0x140, 0, R8A77970_PD_CA53_SCU, R8A77970_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca53-cpu0",  0x200, 0, R8A77970_PD_CA53_CPU0, R8A77970_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu1",  0x200, 1, R8A77970_PD_CA53_CPU1, R8A77970_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "a3ir",       0x180, 0, R8A77970_PD_A3IR,     R8A77970_PD_ALWAYS_ON },
+       { "a2ir0",      0x400, 0, R8A77970_PD_A2IR0,    R8A77970_PD_A3IR },
+       { "a2ir1",      0x400, 1, R8A77970_PD_A2IR1,    R8A77970_PD_A3IR },
+       { "a2dp",       0x400, 2, R8A77970_PD_A2DP,     R8A77970_PD_A3IR },
+       { "a2cn",       0x400, 3, R8A77970_PD_A2CN,     R8A77970_PD_A3IR },
+       { "a2sc0",      0x400, 4, R8A77970_PD_A2SC0,    R8A77970_PD_A3IR },
+       { "a2sc1",      0x400, 5, R8A77970_PD_A2SC1,    R8A77970_PD_A3IR },
+};
+
+const struct rcar_sysc_info r8a77970_sysc_info __initconst = {
+       .areas = r8a77970_areas,
+       .num_areas = ARRAY_SIZE(r8a77970_areas),
+       .extmask_offs = 0x1b0,
+       .extmask_val = BIT(0),
+};
diff --git a/drivers/pmdomain/renesas/r8a77980-sysc.c b/drivers/pmdomain/renesas/r8a77980-sysc.c
new file mode 100644 (file)
index 0000000..39ca84a
--- /dev/null
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car V3H System Controller
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ * Copyright (C) 2018 Cogent Embedded, Inc.
+ */
+
+#include <linux/bits.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a77980-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a77980_areas[] __initconst = {
+       { "always-on",      0, 0, R8A77980_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca53-scu",   0x140, 0, R8A77980_PD_CA53_SCU, R8A77980_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca53-cpu0",  0x200, 0, R8A77980_PD_CA53_CPU0, R8A77980_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu1",  0x200, 1, R8A77980_PD_CA53_CPU1, R8A77980_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu2",  0x200, 2, R8A77980_PD_CA53_CPU2, R8A77980_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu3",  0x200, 3, R8A77980_PD_CA53_CPU3, R8A77980_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "cr7",        0x240, 0, R8A77980_PD_CR7,      R8A77980_PD_ALWAYS_ON },
+       { "a3ir",       0x180, 0, R8A77980_PD_A3IR,     R8A77980_PD_ALWAYS_ON },
+       { "a2ir0",      0x400, 0, R8A77980_PD_A2IR0,    R8A77980_PD_A3IR },
+       { "a2ir1",      0x400, 1, R8A77980_PD_A2IR1,    R8A77980_PD_A3IR },
+       { "a2ir2",      0x400, 2, R8A77980_PD_A2IR2,    R8A77980_PD_A3IR },
+       { "a2ir3",      0x400, 3, R8A77980_PD_A2IR3,    R8A77980_PD_A3IR },
+       { "a2ir4",      0x400, 4, R8A77980_PD_A2IR4,    R8A77980_PD_A3IR },
+       { "a2ir5",      0x400, 5, R8A77980_PD_A2IR5,    R8A77980_PD_A3IR },
+       { "a2sc0",      0x400, 6, R8A77980_PD_A2SC0,    R8A77980_PD_A3IR },
+       { "a2sc1",      0x400, 7, R8A77980_PD_A2SC1,    R8A77980_PD_A3IR },
+       { "a2sc2",      0x400, 8, R8A77980_PD_A2SC2,    R8A77980_PD_A3IR },
+       { "a2sc3",      0x400, 9, R8A77980_PD_A2SC3,    R8A77980_PD_A3IR },
+       { "a2sc4",      0x400, 10, R8A77980_PD_A2SC4,   R8A77980_PD_A3IR },
+       { "a2dp0",      0x400, 11, R8A77980_PD_A2DP0,   R8A77980_PD_A3IR },
+       { "a2dp1",      0x400, 12, R8A77980_PD_A2DP1,   R8A77980_PD_A3IR },
+       { "a2cn",       0x400, 13, R8A77980_PD_A2CN,    R8A77980_PD_A3IR },
+       { "a3vip0",     0x2c0, 0, R8A77980_PD_A3VIP0,   R8A77980_PD_ALWAYS_ON },
+       { "a3vip1",     0x300, 0, R8A77980_PD_A3VIP1,   R8A77980_PD_ALWAYS_ON },
+       { "a3vip2",     0x280, 0, R8A77980_PD_A3VIP2,   R8A77980_PD_ALWAYS_ON },
+};
+
+const struct rcar_sysc_info r8a77980_sysc_info __initconst = {
+       .areas = r8a77980_areas,
+       .num_areas = ARRAY_SIZE(r8a77980_areas),
+       .extmask_offs = 0x138,
+       .extmask_val = BIT(0),
+};
diff --git a/drivers/pmdomain/renesas/r8a77990-sysc.c b/drivers/pmdomain/renesas/r8a77990-sysc.c
new file mode 100644 (file)
index 0000000..9f92737
--- /dev/null
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car E3 System Controller
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ */
+
+#include <linux/bits.h>
+#include <linux/kernel.h>
+#include <linux/sys_soc.h>
+
+#include <dt-bindings/power/r8a77990-sysc.h>
+
+#include "rcar-sysc.h"
+
+static struct rcar_sysc_area r8a77990_areas[] __initdata = {
+       { "always-on",      0, 0, R8A77990_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca53-scu",   0x140, 0, R8A77990_PD_CA53_SCU,  R8A77990_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca53-cpu0",  0x200, 0, R8A77990_PD_CA53_CPU0, R8A77990_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu1",  0x200, 1, R8A77990_PD_CA53_CPU1, R8A77990_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "cr7",        0x240, 0, R8A77990_PD_CR7,      R8A77990_PD_ALWAYS_ON },
+       { "a3vc",       0x380, 0, R8A77990_PD_A3VC,     R8A77990_PD_ALWAYS_ON },
+       { "a2vc1",      0x3c0, 1, R8A77990_PD_A2VC1,    R8A77990_PD_A3VC },
+       { "3dg-a",      0x100, 0, R8A77990_PD_3DG_A,    R8A77990_PD_ALWAYS_ON },
+       { "3dg-b",      0x100, 1, R8A77990_PD_3DG_B,    R8A77990_PD_3DG_A },
+};
+
+/* Fixups for R-Car E3 ES1.0 revision */
+static const struct soc_device_attribute r8a77990[] __initconst = {
+       { .soc_id = "r8a77990", .revision = "ES1.0" },
+       { /* sentinel */ }
+};
+
+static int __init r8a77990_sysc_init(void)
+{
+       if (soc_device_match(r8a77990)) {
+               /* Fix incorrect 3DG hierarchy */
+               swap(r8a77990_areas[7], r8a77990_areas[8]);
+               r8a77990_areas[7].parent = R8A77990_PD_ALWAYS_ON;
+               r8a77990_areas[8].parent = R8A77990_PD_3DG_B;
+       }
+
+       return 0;
+}
+
+const struct rcar_sysc_info r8a77990_sysc_info __initconst = {
+       .init = r8a77990_sysc_init,
+       .areas = r8a77990_areas,
+       .num_areas = ARRAY_SIZE(r8a77990_areas),
+       .extmask_offs = 0x2f8,
+       .extmask_val = BIT(0),
+};
diff --git a/drivers/pmdomain/renesas/r8a77995-sysc.c b/drivers/pmdomain/renesas/r8a77995-sysc.c
new file mode 100644 (file)
index 0000000..efcc67e
--- /dev/null
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car D3 System Controller
+ *
+ * Copyright (C) 2017 Glider bvba
+ */
+
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a77995-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a77995_areas[] __initconst = {
+       { "always-on",     0, 0, R8A77995_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca53-scu",  0x140, 0, R8A77995_PD_CA53_SCU,  R8A77995_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca53-cpu0", 0x200, 0, R8A77995_PD_CA53_CPU0, R8A77995_PD_CA53_SCU,
+         PD_CPU_NOCR },
+};
+
+
+const struct rcar_sysc_info r8a77995_sysc_info __initconst = {
+       .areas = r8a77995_areas,
+       .num_areas = ARRAY_SIZE(r8a77995_areas),
+};
diff --git a/drivers/pmdomain/renesas/r8a779a0-sysc.c b/drivers/pmdomain/renesas/r8a779a0-sysc.c
new file mode 100644 (file)
index 0000000..04f1bc3
--- /dev/null
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car V3U System Controller
+ *
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ */
+
+#include <linux/bits.h>
+#include <linux/clk/renesas.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/of_address.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <dt-bindings/power/r8a779a0-sysc.h>
+
+#include "rcar-gen4-sysc.h"
+
+static struct rcar_gen4_sysc_area r8a779a0_areas[] __initdata = {
+       { "always-on",  R8A779A0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "a3e0",       R8A779A0_PD_A3E0, R8A779A0_PD_ALWAYS_ON, PD_SCU },
+       { "a3e1",       R8A779A0_PD_A3E1, R8A779A0_PD_ALWAYS_ON, PD_SCU },
+       { "a2e0d0",     R8A779A0_PD_A2E0D0, R8A779A0_PD_A3E0, PD_SCU },
+       { "a2e0d1",     R8A779A0_PD_A2E0D1, R8A779A0_PD_A3E0, PD_SCU },
+       { "a2e1d0",     R8A779A0_PD_A2E1D0, R8A779A0_PD_A3E1, PD_SCU },
+       { "a2e1d1",     R8A779A0_PD_A2E1D1, R8A779A0_PD_A3E1, PD_SCU },
+       { "a1e0d0c0",   R8A779A0_PD_A1E0D0C0, R8A779A0_PD_A2E0D0, PD_CPU_NOCR },
+       { "a1e0d0c1",   R8A779A0_PD_A1E0D0C1, R8A779A0_PD_A2E0D0, PD_CPU_NOCR },
+       { "a1e0d1c0",   R8A779A0_PD_A1E0D1C0, R8A779A0_PD_A2E0D1, PD_CPU_NOCR },
+       { "a1e0d1c1",   R8A779A0_PD_A1E0D1C1, R8A779A0_PD_A2E0D1, PD_CPU_NOCR },
+       { "a1e1d0c0",   R8A779A0_PD_A1E1D0C0, R8A779A0_PD_A2E1D0, PD_CPU_NOCR },
+       { "a1e1d0c1",   R8A779A0_PD_A1E1D0C1, R8A779A0_PD_A2E1D0, PD_CPU_NOCR },
+       { "a1e1d1c0",   R8A779A0_PD_A1E1D1C0, R8A779A0_PD_A2E1D1, PD_CPU_NOCR },
+       { "a1e1d1c1",   R8A779A0_PD_A1E1D1C1, R8A779A0_PD_A2E1D1, PD_CPU_NOCR },
+       { "3dg-a",      R8A779A0_PD_3DG_A, R8A779A0_PD_ALWAYS_ON },
+       { "3dg-b",      R8A779A0_PD_3DG_B, R8A779A0_PD_3DG_A },
+       { "a3vip0",     R8A779A0_PD_A3VIP0, R8A779A0_PD_ALWAYS_ON },
+       { "a3vip1",     R8A779A0_PD_A3VIP1, R8A779A0_PD_ALWAYS_ON },
+       { "a3vip3",     R8A779A0_PD_A3VIP3, R8A779A0_PD_ALWAYS_ON },
+       { "a3vip2",     R8A779A0_PD_A3VIP2, R8A779A0_PD_ALWAYS_ON },
+       { "a3isp01",    R8A779A0_PD_A3ISP01, R8A779A0_PD_ALWAYS_ON },
+       { "a3isp23",    R8A779A0_PD_A3ISP23, R8A779A0_PD_ALWAYS_ON },
+       { "a3ir",       R8A779A0_PD_A3IR, R8A779A0_PD_ALWAYS_ON },
+       { "a2cn0",      R8A779A0_PD_A2CN0, R8A779A0_PD_A3IR },
+       { "a2imp01",    R8A779A0_PD_A2IMP01, R8A779A0_PD_A3IR },
+       { "a2dp0",      R8A779A0_PD_A2DP0, R8A779A0_PD_A3IR },
+       { "a2cv0",      R8A779A0_PD_A2CV0, R8A779A0_PD_A3IR },
+       { "a2cv1",      R8A779A0_PD_A2CV1, R8A779A0_PD_A3IR },
+       { "a2cv4",      R8A779A0_PD_A2CV4, R8A779A0_PD_A3IR },
+       { "a2cv6",      R8A779A0_PD_A2CV6, R8A779A0_PD_A3IR },
+       { "a2cn2",      R8A779A0_PD_A2CN2, R8A779A0_PD_A3IR },
+       { "a2imp23",    R8A779A0_PD_A2IMP23, R8A779A0_PD_A3IR },
+       { "a2dp1",      R8A779A0_PD_A2DP1, R8A779A0_PD_A3IR },
+       { "a2cv2",      R8A779A0_PD_A2CV2, R8A779A0_PD_A3IR },
+       { "a2cv3",      R8A779A0_PD_A2CV3, R8A779A0_PD_A3IR },
+       { "a2cv5",      R8A779A0_PD_A2CV5, R8A779A0_PD_A3IR },
+       { "a2cv7",      R8A779A0_PD_A2CV7, R8A779A0_PD_A3IR },
+       { "a2cn1",      R8A779A0_PD_A2CN1, R8A779A0_PD_A3IR },
+       { "a1cnn0",     R8A779A0_PD_A1CNN0, R8A779A0_PD_A2CN0 },
+       { "a1cnn2",     R8A779A0_PD_A1CNN2, R8A779A0_PD_A2CN2 },
+       { "a1dsp0",     R8A779A0_PD_A1DSP0, R8A779A0_PD_A2CN2 },
+       { "a1cnn1",     R8A779A0_PD_A1CNN1, R8A779A0_PD_A2CN1 },
+       { "a1dsp1",     R8A779A0_PD_A1DSP1, R8A779A0_PD_A2CN1 },
+};
+
+const struct rcar_gen4_sysc_info r8a779a0_sysc_info __initconst = {
+       .areas = r8a779a0_areas,
+       .num_areas = ARRAY_SIZE(r8a779a0_areas),
+};
diff --git a/drivers/pmdomain/renesas/r8a779f0-sysc.c b/drivers/pmdomain/renesas/r8a779f0-sysc.c
new file mode 100644 (file)
index 0000000..5602aa6
--- /dev/null
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car S4-8 System Controller
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+#include <linux/bits.h>
+#include <linux/clk/renesas.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/of_address.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <dt-bindings/power/r8a779f0-sysc.h>
+
+#include "rcar-gen4-sysc.h"
+
+static struct rcar_gen4_sysc_area r8a779f0_areas[] __initdata = {
+       { "always-on",  R8A779F0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "a3e0",       R8A779F0_PD_A3E0, R8A779F0_PD_ALWAYS_ON, PD_SCU },
+       { "a3e1",       R8A779F0_PD_A3E1, R8A779F0_PD_ALWAYS_ON, PD_SCU },
+       { "a2e0d0",     R8A779F0_PD_A2E0D0, R8A779F0_PD_A3E0, PD_SCU },
+       { "a2e0d1",     R8A779F0_PD_A2E0D1, R8A779F0_PD_A3E0, PD_SCU },
+       { "a2e1d0",     R8A779F0_PD_A2E1D0, R8A779F0_PD_A3E1, PD_SCU },
+       { "a2e1d1",     R8A779F0_PD_A2E1D1, R8A779F0_PD_A3E1, PD_SCU },
+       { "a1e0d0c0",   R8A779F0_PD_A1E0D0C0, R8A779F0_PD_A2E0D0, PD_CPU_NOCR },
+       { "a1e0d0c1",   R8A779F0_PD_A1E0D0C1, R8A779F0_PD_A2E0D0, PD_CPU_NOCR },
+       { "a1e0d1c0",   R8A779F0_PD_A1E0D1C0, R8A779F0_PD_A2E0D1, PD_CPU_NOCR },
+       { "a1e0d1c1",   R8A779F0_PD_A1E0D1C1, R8A779F0_PD_A2E0D1, PD_CPU_NOCR },
+       { "a1e1d0c0",   R8A779F0_PD_A1E1D0C0, R8A779F0_PD_A2E1D0, PD_CPU_NOCR },
+       { "a1e1d0c1",   R8A779F0_PD_A1E1D0C1, R8A779F0_PD_A2E1D0, PD_CPU_NOCR },
+       { "a1e1d1c0",   R8A779F0_PD_A1E1D1C0, R8A779F0_PD_A2E1D1, PD_CPU_NOCR },
+       { "a1e1d1c1",   R8A779F0_PD_A1E1D1C1, R8A779F0_PD_A2E1D1, PD_CPU_NOCR },
+};
+
+const struct rcar_gen4_sysc_info r8a779f0_sysc_info __initconst = {
+       .areas = r8a779f0_areas,
+       .num_areas = ARRAY_SIZE(r8a779f0_areas),
+};
diff --git a/drivers/pmdomain/renesas/r8a779g0-sysc.c b/drivers/pmdomain/renesas/r8a779g0-sysc.c
new file mode 100644 (file)
index 0000000..b932eba
--- /dev/null
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car V4H System Controller
+ *
+ * Copyright (C) 2022 Renesas Electronics Corp.
+ */
+
+#include <linux/bits.h>
+#include <linux/clk/renesas.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/of_address.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <dt-bindings/power/r8a779g0-sysc.h>
+
+#include "rcar-gen4-sysc.h"
+
+static struct rcar_gen4_sysc_area r8a779g0_areas[] __initdata = {
+       { "always-on",  R8A779G0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "a3e0",       R8A779G0_PD_A3E0, R8A779G0_PD_ALWAYS_ON, PD_SCU },
+       { "a2e0d0",     R8A779G0_PD_A2E0D0, R8A779G0_PD_A3E0, PD_SCU },
+       { "a2e0d1",     R8A779G0_PD_A2E0D1, R8A779G0_PD_A3E0, PD_SCU },
+       { "a1e0d0c0",   R8A779G0_PD_A1E0D0C0, R8A779G0_PD_A2E0D0, PD_CPU_NOCR },
+       { "a1e0d0c1",   R8A779G0_PD_A1E0D0C1, R8A779G0_PD_A2E0D0, PD_CPU_NOCR },
+       { "a1e0d1c0",   R8A779G0_PD_A1E0D1C0, R8A779G0_PD_A2E0D1, PD_CPU_NOCR },
+       { "a1e0d1c1",   R8A779G0_PD_A1E0D1C1, R8A779G0_PD_A2E0D1, PD_CPU_NOCR },
+       { "a33dga",     R8A779G0_PD_A33DGA, R8A779G0_PD_ALWAYS_ON },
+       { "a23dgb",     R8A779G0_PD_A23DGB, R8A779G0_PD_A33DGA },
+       { "a3vip0",     R8A779G0_PD_A3VIP0, R8A779G0_PD_ALWAYS_ON },
+       { "a3vip1",     R8A779G0_PD_A3VIP1, R8A779G0_PD_ALWAYS_ON },
+       { "a3vip2",     R8A779G0_PD_A3VIP2, R8A779G0_PD_ALWAYS_ON },
+       { "a3dul",      R8A779G0_PD_A3DUL, R8A779G0_PD_ALWAYS_ON },
+       { "a3isp0",     R8A779G0_PD_A3ISP0, R8A779G0_PD_ALWAYS_ON },
+       { "a3isp1",     R8A779G0_PD_A3ISP1, R8A779G0_PD_ALWAYS_ON },
+       { "a3ir",       R8A779G0_PD_A3IR, R8A779G0_PD_ALWAYS_ON },
+       { "a2cn0",      R8A779G0_PD_A2CN0, R8A779G0_PD_A3IR },
+       { "a1cnn0",     R8A779G0_PD_A1CNN0, R8A779G0_PD_A2CN0 },
+       { "a1dsp0",     R8A779G0_PD_A1DSP0, R8A779G0_PD_A2CN0 },
+       { "a1dsp1",     R8A779G0_PD_A1DSP1, R8A779G0_PD_A2CN0 },
+       { "a1dsp2",     R8A779G0_PD_A1DSP2, R8A779G0_PD_A2CN0 },
+       { "a1dsp3",     R8A779G0_PD_A1DSP3, R8A779G0_PD_A2CN0 },
+       { "a2imp01",    R8A779G0_PD_A2IMP01, R8A779G0_PD_A3IR },
+       { "a2imp23",    R8A779G0_PD_A2IMP23, R8A779G0_PD_A3IR },
+       { "a2psc",      R8A779G0_PD_A2PSC, R8A779G0_PD_A3IR },
+       { "a2dma",      R8A779G0_PD_A2DMA, R8A779G0_PD_A3IR },
+       { "a2cv0",      R8A779G0_PD_A2CV0, R8A779G0_PD_A3IR },
+       { "a2cv1",      R8A779G0_PD_A2CV1, R8A779G0_PD_A3IR },
+       { "a2cv2",      R8A779G0_PD_A2CV2, R8A779G0_PD_A3IR },
+       { "a2cv3",      R8A779G0_PD_A2CV3, R8A779G0_PD_A3IR },
+};
+
+const struct rcar_gen4_sysc_info r8a779g0_sysc_info __initconst = {
+       .areas = r8a779g0_areas,
+       .num_areas = ARRAY_SIZE(r8a779g0_areas),
+};
diff --git a/drivers/pmdomain/renesas/rcar-gen4-sysc.c b/drivers/pmdomain/renesas/rcar-gen4-sysc.c
new file mode 100644 (file)
index 0000000..9e5e6e0
--- /dev/null
@@ -0,0 +1,379 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R-Car Gen4 SYSC Power management support
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+#include <linux/bits.h>
+#include <linux/clk/renesas.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/of_address.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include "rcar-gen4-sysc.h"
+
+/* SYSC Common */
+#define SYSCSR         0x000   /* SYSC Status Register */
+#define SYSCPONSR(x)   (0x800 + ((x) * 0x4)) /* Power-ON Status Register 0 */
+#define SYSCPOFFSR(x)  (0x808 + ((x) * 0x4)) /* Power-OFF Status Register */
+#define SYSCISCR(x)    (0x810 + ((x) * 0x4)) /* Interrupt Status/Clear Register */
+#define SYSCIER(x)     (0x820 + ((x) * 0x4)) /* Interrupt Enable Register */
+#define SYSCIMR(x)     (0x830 + ((x) * 0x4)) /* Interrupt Mask Register */
+
+/* Power Domain Registers */
+#define PDRSR(n)       (0x1000 + ((n) * 0x40))
+#define PDRONCR(n)     (0x1004 + ((n) * 0x40))
+#define PDROFFCR(n)    (0x1008 + ((n) * 0x40))
+#define PDRESR(n)      (0x100C + ((n) * 0x40))
+
+/* PWRON/PWROFF */
+#define PWRON_PWROFF           BIT(0)  /* Power-ON/OFF request */
+
+/* PDRESR */
+#define PDRESR_ERR             BIT(0)
+
+/* PDRSR */
+#define PDRSR_OFF              BIT(0)  /* Power-OFF state */
+#define PDRSR_ON               BIT(4)  /* Power-ON state */
+#define PDRSR_OFF_STATE                BIT(8)  /* Processing Power-OFF sequence */
+#define PDRSR_ON_STATE         BIT(12) /* Processing Power-ON sequence */
+
+#define SYSCSR_BUSY            GENMASK(1, 0)   /* All bit sets is not busy */
+
+#define SYSCSR_TIMEOUT         10000
+#define SYSCSR_DELAY_US                10
+
+#define PDRESR_RETRIES         1000
+#define PDRESR_DELAY_US                10
+
+#define SYSCISR_TIMEOUT                10000
+#define SYSCISR_DELAY_US       10
+
+#define RCAR_GEN4_PD_ALWAYS_ON 64
+#define NUM_DOMAINS_EACH_REG   BITS_PER_TYPE(u32)
+
+static void __iomem *rcar_gen4_sysc_base;
+static DEFINE_SPINLOCK(rcar_gen4_sysc_lock); /* SMP CPUs + I/O devices */
+
+static int rcar_gen4_sysc_pwr_on_off(u8 pdr, bool on)
+{
+       unsigned int reg_offs;
+       u32 val;
+       int ret;
+
+       if (on)
+               reg_offs = PDRONCR(pdr);
+       else
+               reg_offs = PDROFFCR(pdr);
+
+       /* Wait until SYSC is ready to accept a power request */
+       ret = readl_poll_timeout_atomic(rcar_gen4_sysc_base + SYSCSR, val,
+                                       (val & SYSCSR_BUSY) == SYSCSR_BUSY,
+                                       SYSCSR_DELAY_US, SYSCSR_TIMEOUT);
+       if (ret < 0)
+               return -EAGAIN;
+
+       /* Submit power shutoff or power resume request */
+       iowrite32(PWRON_PWROFF, rcar_gen4_sysc_base + reg_offs);
+
+       return 0;
+}
+
+static int clear_irq_flags(unsigned int reg_idx, unsigned int isr_mask)
+{
+       u32 val;
+       int ret;
+
+       iowrite32(isr_mask, rcar_gen4_sysc_base + SYSCISCR(reg_idx));
+
+       ret = readl_poll_timeout_atomic(rcar_gen4_sysc_base + SYSCISCR(reg_idx),
+                                       val, !(val & isr_mask),
+                                       SYSCISR_DELAY_US, SYSCISR_TIMEOUT);
+       if (ret < 0) {
+               pr_err("\n %s : Can not clear IRQ flags in SYSCISCR", __func__);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int rcar_gen4_sysc_power(u8 pdr, bool on)
+{
+       unsigned int isr_mask;
+       unsigned int reg_idx, bit_idx;
+       unsigned int status;
+       unsigned long flags;
+       int ret = 0;
+       u32 val;
+       int k;
+
+       spin_lock_irqsave(&rcar_gen4_sysc_lock, flags);
+
+       reg_idx = pdr / NUM_DOMAINS_EACH_REG;
+       bit_idx = pdr % NUM_DOMAINS_EACH_REG;
+
+       isr_mask = BIT(bit_idx);
+
+       /*
+        * The interrupt source needs to be enabled, but masked, to prevent the
+        * CPU from receiving it.
+        */
+       iowrite32(ioread32(rcar_gen4_sysc_base + SYSCIER(reg_idx)) | isr_mask,
+                 rcar_gen4_sysc_base + SYSCIER(reg_idx));
+       iowrite32(ioread32(rcar_gen4_sysc_base + SYSCIMR(reg_idx)) | isr_mask,
+                 rcar_gen4_sysc_base + SYSCIMR(reg_idx));
+
+       ret = clear_irq_flags(reg_idx, isr_mask);
+       if (ret)
+               goto out;
+
+       /* Submit power shutoff or resume request until it was accepted */
+       for (k = 0; k < PDRESR_RETRIES; k++) {
+               ret = rcar_gen4_sysc_pwr_on_off(pdr, on);
+               if (ret)
+                       goto out;
+
+               status = ioread32(rcar_gen4_sysc_base + PDRESR(pdr));
+               if (!(status & PDRESR_ERR))
+                       break;
+
+               udelay(PDRESR_DELAY_US);
+       }
+
+       if (k == PDRESR_RETRIES) {
+               ret = -EIO;
+               goto out;
+       }
+
+       /* Wait until the power shutoff or resume request has completed * */
+       ret = readl_poll_timeout_atomic(rcar_gen4_sysc_base + SYSCISCR(reg_idx),
+                                       val, (val & isr_mask),
+                                       SYSCISR_DELAY_US, SYSCISR_TIMEOUT);
+       if (ret < 0) {
+               ret = -EIO;
+               goto out;
+       }
+
+       /* Clear interrupt flags */
+       ret = clear_irq_flags(reg_idx, isr_mask);
+       if (ret)
+               goto out;
+
+ out:
+       spin_unlock_irqrestore(&rcar_gen4_sysc_lock, flags);
+
+       pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off",
+                pdr, ioread32(rcar_gen4_sysc_base + SYSCISCR(reg_idx)), ret);
+       return ret;
+}
+
+static bool rcar_gen4_sysc_power_is_off(u8 pdr)
+{
+       unsigned int st;
+
+       st = ioread32(rcar_gen4_sysc_base + PDRSR(pdr));
+
+       if (st & PDRSR_OFF)
+               return true;
+
+       return false;
+}
+
+struct rcar_gen4_sysc_pd {
+       struct generic_pm_domain genpd;
+       u8 pdr;
+       unsigned int flags;
+       char name[];
+};
+
+static inline struct rcar_gen4_sysc_pd *to_rcar_gen4_pd(struct generic_pm_domain *d)
+{
+       return container_of(d, struct rcar_gen4_sysc_pd, genpd);
+}
+
+static int rcar_gen4_sysc_pd_power_off(struct generic_pm_domain *genpd)
+{
+       struct rcar_gen4_sysc_pd *pd = to_rcar_gen4_pd(genpd);
+
+       pr_debug("%s: %s\n", __func__, genpd->name);
+       return rcar_gen4_sysc_power(pd->pdr, false);
+}
+
+static int rcar_gen4_sysc_pd_power_on(struct generic_pm_domain *genpd)
+{
+       struct rcar_gen4_sysc_pd *pd = to_rcar_gen4_pd(genpd);
+
+       pr_debug("%s: %s\n", __func__, genpd->name);
+       return rcar_gen4_sysc_power(pd->pdr, true);
+}
+
+static int __init rcar_gen4_sysc_pd_setup(struct rcar_gen4_sysc_pd *pd)
+{
+       struct generic_pm_domain *genpd = &pd->genpd;
+       const char *name = pd->genpd.name;
+       int error;
+
+       if (pd->flags & PD_CPU) {
+               /*
+                * This domain contains a CPU core and therefore it should
+                * only be turned off if the CPU is not in use.
+                */
+               pr_debug("PM domain %s contains %s\n", name, "CPU");
+               genpd->flags |= GENPD_FLAG_ALWAYS_ON;
+       } else if (pd->flags & PD_SCU) {
+               /*
+                * This domain contains an SCU and cache-controller, and
+                * therefore it should only be turned off if the CPU cores are
+                * not in use.
+                */
+               pr_debug("PM domain %s contains %s\n", name, "SCU");
+               genpd->flags |= GENPD_FLAG_ALWAYS_ON;
+       } else if (pd->flags & PD_NO_CR) {
+               /*
+                * This domain cannot be turned off.
+                */
+               genpd->flags |= GENPD_FLAG_ALWAYS_ON;
+       }
+
+       if (!(pd->flags & (PD_CPU | PD_SCU))) {
+               /* Enable Clock Domain for I/O devices */
+               genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
+               genpd->attach_dev = cpg_mssr_attach_dev;
+               genpd->detach_dev = cpg_mssr_detach_dev;
+       }
+
+       genpd->power_off = rcar_gen4_sysc_pd_power_off;
+       genpd->power_on = rcar_gen4_sysc_pd_power_on;
+
+       if (pd->flags & (PD_CPU | PD_NO_CR)) {
+               /* Skip CPUs (handled by SMP code) and areas without control */
+               pr_debug("%s: Not touching %s\n", __func__, genpd->name);
+               goto finalize;
+       }
+
+       if (!rcar_gen4_sysc_power_is_off(pd->pdr)) {
+               pr_debug("%s: %s is already powered\n", __func__, genpd->name);
+               goto finalize;
+       }
+
+       rcar_gen4_sysc_power(pd->pdr, true);
+
+finalize:
+       error = pm_genpd_init(genpd, &simple_qos_governor, false);
+       if (error)
+               pr_err("Failed to init PM domain %s: %d\n", name, error);
+
+       return error;
+}
+
+static const struct of_device_id rcar_gen4_sysc_matches[] __initconst = {
+#ifdef CONFIG_SYSC_R8A779A0
+       { .compatible = "renesas,r8a779a0-sysc", .data = &r8a779a0_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A779F0
+       { .compatible = "renesas,r8a779f0-sysc", .data = &r8a779f0_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A779G0
+       { .compatible = "renesas,r8a779g0-sysc", .data = &r8a779g0_sysc_info },
+#endif
+       { /* sentinel */ }
+};
+
+struct rcar_gen4_pm_domains {
+       struct genpd_onecell_data onecell_data;
+       struct generic_pm_domain *domains[RCAR_GEN4_PD_ALWAYS_ON + 1];
+};
+
+static struct genpd_onecell_data *rcar_gen4_sysc_onecell_data;
+
+static int __init rcar_gen4_sysc_pd_init(void)
+{
+       const struct rcar_gen4_sysc_info *info;
+       const struct of_device_id *match;
+       struct rcar_gen4_pm_domains *domains;
+       struct device_node *np;
+       void __iomem *base;
+       unsigned int i;
+       int error;
+
+       np = of_find_matching_node_and_match(NULL, rcar_gen4_sysc_matches, &match);
+       if (!np)
+               return -ENODEV;
+
+       info = match->data;
+
+       base = of_iomap(np, 0);
+       if (!base) {
+               pr_warn("%pOF: Cannot map regs\n", np);
+               error = -ENOMEM;
+               goto out_put;
+       }
+
+       rcar_gen4_sysc_base = base;
+
+       domains = kzalloc(sizeof(*domains), GFP_KERNEL);
+       if (!domains) {
+               error = -ENOMEM;
+               goto out_put;
+       }
+
+       domains->onecell_data.domains = domains->domains;
+       domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains);
+       rcar_gen4_sysc_onecell_data = &domains->onecell_data;
+
+       for (i = 0; i < info->num_areas; i++) {
+               const struct rcar_gen4_sysc_area *area = &info->areas[i];
+               struct rcar_gen4_sysc_pd *pd;
+               size_t n;
+
+               if (!area->name) {
+                       /* Skip NULLified area */
+                       continue;
+               }
+
+               n = strlen(area->name) + 1;
+               pd = kzalloc(sizeof(*pd) + n, GFP_KERNEL);
+               if (!pd) {
+                       error = -ENOMEM;
+                       goto out_put;
+               }
+
+               memcpy(pd->name, area->name, n);
+               pd->genpd.name = pd->name;
+               pd->pdr = area->pdr;
+               pd->flags = area->flags;
+
+               error = rcar_gen4_sysc_pd_setup(pd);
+               if (error)
+                       goto out_put;
+
+               domains->domains[area->pdr] = &pd->genpd;
+
+               if (area->parent < 0)
+                       continue;
+
+               error = pm_genpd_add_subdomain(domains->domains[area->parent],
+                                              &pd->genpd);
+               if (error) {
+                       pr_warn("Failed to add PM subdomain %s to parent %u\n",
+                               area->name, area->parent);
+                       goto out_put;
+               }
+       }
+
+       error = of_genpd_add_provider_onecell(np, &domains->onecell_data);
+
+out_put:
+       of_node_put(np);
+       return error;
+}
+early_initcall(rcar_gen4_sysc_pd_init);
diff --git a/drivers/pmdomain/renesas/rcar-gen4-sysc.h b/drivers/pmdomain/renesas/rcar-gen4-sysc.h
new file mode 100644 (file)
index 0000000..388cfa8
--- /dev/null
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * R-Car Gen4 System Controller
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+#ifndef __SOC_RENESAS_RCAR_GEN4_SYSC_H__
+#define __SOC_RENESAS_RCAR_GEN4_SYSC_H__
+
+#include <linux/types.h>
+
+/*
+ * Power Domain flags
+ */
+#define PD_CPU         BIT(0)  /* Area contains main CPU core */
+#define PD_SCU         BIT(1)  /* Area contains SCU and L2 cache */
+#define PD_NO_CR       BIT(2)  /* Area lacks PWR{ON,OFF}CR registers */
+
+#define PD_CPU_NOCR    (PD_CPU | PD_NO_CR) /* CPU area lacks CR */
+#define PD_ALWAYS_ON   PD_NO_CR          /* Always-on area */
+
+/*
+ * Description of a Power Area
+ */
+struct rcar_gen4_sysc_area {
+       const char *name;
+       u8 pdr;                 /* PDRn */
+       s8 parent;              /* -1 if none */
+       u8 flags;               /* See PD_* */
+};
+
+/*
+ * SoC-specific Power Area Description
+ */
+struct rcar_gen4_sysc_info {
+       const struct rcar_gen4_sysc_area *areas;
+       unsigned int num_areas;
+};
+
+extern const struct rcar_gen4_sysc_info r8a779a0_sysc_info;
+extern const struct rcar_gen4_sysc_info r8a779f0_sysc_info;
+extern const struct rcar_gen4_sysc_info r8a779g0_sysc_info;
+
+#endif /* __SOC_RENESAS_RCAR_GEN4_SYSC_H__ */
diff --git a/drivers/pmdomain/renesas/rcar-sysc.c b/drivers/pmdomain/renesas/rcar-sysc.c
new file mode 100644 (file)
index 0000000..eed4769
--- /dev/null
@@ -0,0 +1,494 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R-Car SYSC Power management support
+ *
+ * Copyright (C) 2014  Magnus Damm
+ * Copyright (C) 2015-2017 Glider bvba
+ */
+
+#include <linux/clk/renesas.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/of_address.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/soc/renesas/rcar-sysc.h>
+
+#include "rcar-sysc.h"
+
+/* SYSC Common */
+#define SYSCSR                 0x00    /* SYSC Status Register */
+#define SYSCISR                        0x04    /* Interrupt Status Register */
+#define SYSCISCR               0x08    /* Interrupt Status Clear Register */
+#define SYSCIER                        0x0c    /* Interrupt Enable Register */
+#define SYSCIMR                        0x10    /* Interrupt Mask Register */
+
+/* SYSC Status Register */
+#define SYSCSR_PONENB          1       /* Ready for power resume requests */
+#define SYSCSR_POFFENB         0       /* Ready for power shutoff requests */
+
+/*
+ * Power Control Register Offsets inside the register block for each domain
+ * Note: The "CR" registers for ARM cores exist on H1 only
+ *      Use WFI to power off, CPG/APMU to resume ARM cores on R-Car Gen2
+ *      Use PSCI on R-Car Gen3
+ */
+#define PWRSR_OFFS             0x00    /* Power Status Register */
+#define PWROFFCR_OFFS          0x04    /* Power Shutoff Control Register */
+#define PWROFFSR_OFFS          0x08    /* Power Shutoff Status Register */
+#define PWRONCR_OFFS           0x0c    /* Power Resume Control Register */
+#define PWRONSR_OFFS           0x10    /* Power Resume Status Register */
+#define PWRER_OFFS             0x14    /* Power Shutoff/Resume Error */
+
+
+#define SYSCSR_TIMEOUT         100
+#define SYSCSR_DELAY_US                1
+
+#define PWRER_RETRIES          100
+#define PWRER_DELAY_US         1
+
+#define SYSCISR_TIMEOUT                1000
+#define SYSCISR_DELAY_US       1
+
+#define RCAR_PD_ALWAYS_ON      32      /* Always-on power area */
+
+struct rcar_sysc_ch {
+       u16 chan_offs;
+       u8 chan_bit;
+       u8 isr_bit;
+};
+
+static void __iomem *rcar_sysc_base;
+static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */
+static u32 rcar_sysc_extmask_offs, rcar_sysc_extmask_val;
+
+static int rcar_sysc_pwr_on_off(const struct rcar_sysc_ch *sysc_ch, bool on)
+{
+       unsigned int sr_bit, reg_offs;
+       u32 val;
+       int ret;
+
+       if (on) {
+               sr_bit = SYSCSR_PONENB;
+               reg_offs = PWRONCR_OFFS;
+       } else {
+               sr_bit = SYSCSR_POFFENB;
+               reg_offs = PWROFFCR_OFFS;
+       }
+
+       /* Wait until SYSC is ready to accept a power request */
+       ret = readl_poll_timeout_atomic(rcar_sysc_base + SYSCSR, val,
+                                       val & BIT(sr_bit), SYSCSR_DELAY_US,
+                                       SYSCSR_TIMEOUT);
+       if (ret)
+               return -EAGAIN;
+
+       /* Submit power shutoff or power resume request */
+       iowrite32(BIT(sysc_ch->chan_bit),
+                 rcar_sysc_base + sysc_ch->chan_offs + reg_offs);
+
+       return 0;
+}
+
+static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on)
+{
+       unsigned int isr_mask = BIT(sysc_ch->isr_bit);
+       unsigned int chan_mask = BIT(sysc_ch->chan_bit);
+       unsigned int status, k;
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&rcar_sysc_lock, flags);
+
+       /*
+        * Mask external power requests for CPU or 3DG domains
+        */
+       if (rcar_sysc_extmask_val) {
+               iowrite32(rcar_sysc_extmask_val,
+                         rcar_sysc_base + rcar_sysc_extmask_offs);
+       }
+
+       /*
+        * The interrupt source needs to be enabled, but masked, to prevent the
+        * CPU from receiving it.
+        */
+       iowrite32(ioread32(rcar_sysc_base + SYSCIMR) | isr_mask,
+                 rcar_sysc_base + SYSCIMR);
+       iowrite32(ioread32(rcar_sysc_base + SYSCIER) | isr_mask,
+                 rcar_sysc_base + SYSCIER);
+
+       iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
+
+       /* Submit power shutoff or resume request until it was accepted */
+       for (k = 0; k < PWRER_RETRIES; k++) {
+               ret = rcar_sysc_pwr_on_off(sysc_ch, on);
+               if (ret)
+                       goto out;
+
+               status = ioread32(rcar_sysc_base +
+                                 sysc_ch->chan_offs + PWRER_OFFS);
+               if (!(status & chan_mask))
+                       break;
+
+               udelay(PWRER_DELAY_US);
+       }
+
+       if (k == PWRER_RETRIES) {
+               ret = -EIO;
+               goto out;
+       }
+
+       /* Wait until the power shutoff or resume request has completed * */
+       ret = readl_poll_timeout_atomic(rcar_sysc_base + SYSCISR, status,
+                                       status & isr_mask, SYSCISR_DELAY_US,
+                                       SYSCISR_TIMEOUT);
+       if (ret)
+               ret = -EIO;
+
+       iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
+
+ out:
+       if (rcar_sysc_extmask_val)
+               iowrite32(0, rcar_sysc_base + rcar_sysc_extmask_offs);
+
+       spin_unlock_irqrestore(&rcar_sysc_lock, flags);
+
+       pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off",
+                sysc_ch->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret);
+       return ret;
+}
+
+static bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch)
+{
+       unsigned int st;
+
+       st = ioread32(rcar_sysc_base + sysc_ch->chan_offs + PWRSR_OFFS);
+       if (st & BIT(sysc_ch->chan_bit))
+               return true;
+
+       return false;
+}
+
+struct rcar_sysc_pd {
+       struct generic_pm_domain genpd;
+       struct rcar_sysc_ch ch;
+       unsigned int flags;
+       char name[];
+};
+
+static inline struct rcar_sysc_pd *to_rcar_pd(struct generic_pm_domain *d)
+{
+       return container_of(d, struct rcar_sysc_pd, genpd);
+}
+
+static int rcar_sysc_pd_power_off(struct generic_pm_domain *genpd)
+{
+       struct rcar_sysc_pd *pd = to_rcar_pd(genpd);
+
+       pr_debug("%s: %s\n", __func__, genpd->name);
+       return rcar_sysc_power(&pd->ch, false);
+}
+
+static int rcar_sysc_pd_power_on(struct generic_pm_domain *genpd)
+{
+       struct rcar_sysc_pd *pd = to_rcar_pd(genpd);
+
+       pr_debug("%s: %s\n", __func__, genpd->name);
+       return rcar_sysc_power(&pd->ch, true);
+}
+
+static bool has_cpg_mstp;
+
+static int __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd)
+{
+       struct generic_pm_domain *genpd = &pd->genpd;
+       const char *name = pd->genpd.name;
+       int error;
+
+       if (pd->flags & PD_CPU) {
+               /*
+                * This domain contains a CPU core and therefore it should
+                * only be turned off if the CPU is not in use.
+                */
+               pr_debug("PM domain %s contains %s\n", name, "CPU");
+               genpd->flags |= GENPD_FLAG_ALWAYS_ON;
+       } else if (pd->flags & PD_SCU) {
+               /*
+                * This domain contains an SCU and cache-controller, and
+                * therefore it should only be turned off if the CPU cores are
+                * not in use.
+                */
+               pr_debug("PM domain %s contains %s\n", name, "SCU");
+               genpd->flags |= GENPD_FLAG_ALWAYS_ON;
+       } else if (pd->flags & PD_NO_CR) {
+               /*
+                * This domain cannot be turned off.
+                */
+               genpd->flags |= GENPD_FLAG_ALWAYS_ON;
+       }
+
+       if (!(pd->flags & (PD_CPU | PD_SCU))) {
+               /* Enable Clock Domain for I/O devices */
+               genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
+               if (has_cpg_mstp) {
+                       genpd->attach_dev = cpg_mstp_attach_dev;
+                       genpd->detach_dev = cpg_mstp_detach_dev;
+               } else {
+                       genpd->attach_dev = cpg_mssr_attach_dev;
+                       genpd->detach_dev = cpg_mssr_detach_dev;
+               }
+       }
+
+       genpd->power_off = rcar_sysc_pd_power_off;
+       genpd->power_on = rcar_sysc_pd_power_on;
+
+       if (pd->flags & (PD_CPU | PD_NO_CR)) {
+               /* Skip CPUs (handled by SMP code) and areas without control */
+               pr_debug("%s: Not touching %s\n", __func__, genpd->name);
+               goto finalize;
+       }
+
+       if (!rcar_sysc_power_is_off(&pd->ch)) {
+               pr_debug("%s: %s is already powered\n", __func__, genpd->name);
+               goto finalize;
+       }
+
+       rcar_sysc_power(&pd->ch, true);
+
+finalize:
+       error = pm_genpd_init(genpd, &simple_qos_governor, false);
+       if (error)
+               pr_err("Failed to init PM domain %s: %d\n", name, error);
+
+       return error;
+}
+
+static const struct of_device_id rcar_sysc_matches[] __initconst = {
+#ifdef CONFIG_SYSC_R8A7742
+       { .compatible = "renesas,r8a7742-sysc", .data = &r8a7742_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A7743
+       { .compatible = "renesas,r8a7743-sysc", .data = &r8a7743_sysc_info },
+       /* RZ/G1N is identical to RZ/G2M w.r.t. power domains. */
+       { .compatible = "renesas,r8a7744-sysc", .data = &r8a7743_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A7745
+       { .compatible = "renesas,r8a7745-sysc", .data = &r8a7745_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A77470
+       { .compatible = "renesas,r8a77470-sysc", .data = &r8a77470_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A774A1
+       { .compatible = "renesas,r8a774a1-sysc", .data = &r8a774a1_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A774B1
+       { .compatible = "renesas,r8a774b1-sysc", .data = &r8a774b1_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A774C0
+       { .compatible = "renesas,r8a774c0-sysc", .data = &r8a774c0_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A774E1
+       { .compatible = "renesas,r8a774e1-sysc", .data = &r8a774e1_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A7779
+       { .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A7790
+       { .compatible = "renesas,r8a7790-sysc", .data = &r8a7790_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A7791
+       { .compatible = "renesas,r8a7791-sysc", .data = &r8a7791_sysc_info },
+       /* R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. */
+       { .compatible = "renesas,r8a7793-sysc", .data = &r8a7791_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A7792
+       { .compatible = "renesas,r8a7792-sysc", .data = &r8a7792_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A7794
+       { .compatible = "renesas,r8a7794-sysc", .data = &r8a7794_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A7795
+       { .compatible = "renesas,r8a7795-sysc", .data = &r8a7795_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A77960
+       { .compatible = "renesas,r8a7796-sysc", .data = &r8a77960_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A77961
+       { .compatible = "renesas,r8a77961-sysc", .data = &r8a77961_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A77965
+       { .compatible = "renesas,r8a77965-sysc", .data = &r8a77965_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A77970
+       { .compatible = "renesas,r8a77970-sysc", .data = &r8a77970_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A77980
+       { .compatible = "renesas,r8a77980-sysc", .data = &r8a77980_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A77990
+       { .compatible = "renesas,r8a77990-sysc", .data = &r8a77990_sysc_info },
+#endif
+#ifdef CONFIG_SYSC_R8A77995
+       { .compatible = "renesas,r8a77995-sysc", .data = &r8a77995_sysc_info },
+#endif
+       { /* sentinel */ }
+};
+
+struct rcar_pm_domains {
+       struct genpd_onecell_data onecell_data;
+       struct generic_pm_domain *domains[RCAR_PD_ALWAYS_ON + 1];
+};
+
+static struct genpd_onecell_data *rcar_sysc_onecell_data;
+
+static int __init rcar_sysc_pd_init(void)
+{
+       const struct rcar_sysc_info *info;
+       const struct of_device_id *match;
+       struct rcar_pm_domains *domains;
+       struct device_node *np;
+       void __iomem *base;
+       unsigned int i;
+       int error;
+
+       np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match);
+       if (!np)
+               return -ENODEV;
+
+       info = match->data;
+
+       if (info->init) {
+               error = info->init();
+               if (error)
+                       goto out_put;
+       }
+
+       has_cpg_mstp = of_find_compatible_node(NULL, NULL,
+                                              "renesas,cpg-mstp-clocks");
+
+       base = of_iomap(np, 0);
+       if (!base) {
+               pr_warn("%pOF: Cannot map regs\n", np);
+               error = -ENOMEM;
+               goto out_put;
+       }
+
+       rcar_sysc_base = base;
+
+       /* Optional External Request Mask Register */
+       rcar_sysc_extmask_offs = info->extmask_offs;
+       rcar_sysc_extmask_val = info->extmask_val;
+
+       domains = kzalloc(sizeof(*domains), GFP_KERNEL);
+       if (!domains) {
+               error = -ENOMEM;
+               goto out_put;
+       }
+
+       domains->onecell_data.domains = domains->domains;
+       domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains);
+       rcar_sysc_onecell_data = &domains->onecell_data;
+
+       for (i = 0; i < info->num_areas; i++) {
+               const struct rcar_sysc_area *area = &info->areas[i];
+               struct rcar_sysc_pd *pd;
+               size_t n;
+
+               if (!area->name) {
+                       /* Skip NULLified area */
+                       continue;
+               }
+
+               n = strlen(area->name) + 1;
+               pd = kzalloc(sizeof(*pd) + n, GFP_KERNEL);
+               if (!pd) {
+                       error = -ENOMEM;
+                       goto out_put;
+               }
+
+               memcpy(pd->name, area->name, n);
+               pd->genpd.name = pd->name;
+               pd->ch.chan_offs = area->chan_offs;
+               pd->ch.chan_bit = area->chan_bit;
+               pd->ch.isr_bit = area->isr_bit;
+               pd->flags = area->flags;
+
+               error = rcar_sysc_pd_setup(pd);
+               if (error)
+                       goto out_put;
+
+               domains->domains[area->isr_bit] = &pd->genpd;
+
+               if (area->parent < 0)
+                       continue;
+
+               error = pm_genpd_add_subdomain(domains->domains[area->parent],
+                                              &pd->genpd);
+               if (error) {
+                       pr_warn("Failed to add PM subdomain %s to parent %u\n",
+                               area->name, area->parent);
+                       goto out_put;
+               }
+       }
+
+       error = of_genpd_add_provider_onecell(np, &domains->onecell_data);
+       if (!error)
+               fwnode_dev_initialized(of_fwnode_handle(np), true);
+
+out_put:
+       of_node_put(np);
+       return error;
+}
+early_initcall(rcar_sysc_pd_init);
+
+void __init rcar_sysc_nullify(struct rcar_sysc_area *areas,
+                             unsigned int num_areas, u8 id)
+{
+       unsigned int i;
+
+       for (i = 0; i < num_areas; i++)
+               if (areas[i].isr_bit == id) {
+                       areas[i].name = NULL;
+                       return;
+               }
+}
+
+#ifdef CONFIG_ARCH_R8A7779
+static int rcar_sysc_power_cpu(unsigned int idx, bool on)
+{
+       struct generic_pm_domain *genpd;
+       struct rcar_sysc_pd *pd;
+       unsigned int i;
+
+       if (!rcar_sysc_onecell_data)
+               return -ENODEV;
+
+       for (i = 0; i < rcar_sysc_onecell_data->num_domains; i++) {
+               genpd = rcar_sysc_onecell_data->domains[i];
+               if (!genpd)
+                       continue;
+
+               pd = to_rcar_pd(genpd);
+               if (!(pd->flags & PD_CPU) || pd->ch.chan_bit != idx)
+                       continue;
+
+               return rcar_sysc_power(&pd->ch, on);
+       }
+
+       return -ENOENT;
+}
+
+int rcar_sysc_power_down_cpu(unsigned int cpu)
+{
+       return rcar_sysc_power_cpu(cpu, false);
+}
+
+int rcar_sysc_power_up_cpu(unsigned int cpu)
+{
+       return rcar_sysc_power_cpu(cpu, true);
+}
+#endif /* CONFIG_ARCH_R8A7779 */
diff --git a/drivers/pmdomain/renesas/rcar-sysc.h b/drivers/pmdomain/renesas/rcar-sysc.h
new file mode 100644 (file)
index 0000000..266c599
--- /dev/null
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Renesas R-Car System Controller
+ *
+ * Copyright (C) 2016 Glider bvba
+ */
+#ifndef __SOC_RENESAS_RCAR_SYSC_H__
+#define __SOC_RENESAS_RCAR_SYSC_H__
+
+#include <linux/types.h>
+
+
+/*
+ * Power Domain flags
+ */
+#define PD_CPU         BIT(0)  /* Area contains main CPU core */
+#define PD_SCU         BIT(1)  /* Area contains SCU and L2 cache */
+#define PD_NO_CR       BIT(2)  /* Area lacks PWR{ON,OFF}CR registers */
+
+#define PD_CPU_CR      PD_CPU            /* CPU area has CR (R-Car H1) */
+#define PD_CPU_NOCR    PD_CPU | PD_NO_CR /* CPU area lacks CR (R-Car Gen2/3) */
+#define PD_ALWAYS_ON   PD_NO_CR          /* Always-on area */
+
+
+/*
+ * Description of a Power Area
+ */
+
+struct rcar_sysc_area {
+       const char *name;
+       u16 chan_offs;          /* Offset of PWRSR register for this area */
+       u8 chan_bit;            /* Bit in PWR* (except for PWRUP in PWRSR) */
+       u8 isr_bit;             /* Bit in SYSCI*R */
+       s8 parent;              /* -1 if none */
+       u8 flags;               /* See PD_* */
+};
+
+
+/*
+ * SoC-specific Power Area Description
+ */
+
+struct rcar_sysc_info {
+       int (*init)(void);      /* Optional */
+       const struct rcar_sysc_area *areas;
+       unsigned int num_areas;
+       /* Optional External Request Mask Register */
+       u32 extmask_offs;       /* SYSCEXTMASK register offset */
+       u32 extmask_val;        /* SYSCEXTMASK register mask value */
+};
+
+extern const struct rcar_sysc_info r8a7742_sysc_info;
+extern const struct rcar_sysc_info r8a7743_sysc_info;
+extern const struct rcar_sysc_info r8a7745_sysc_info;
+extern const struct rcar_sysc_info r8a77470_sysc_info;
+extern const struct rcar_sysc_info r8a774a1_sysc_info;
+extern const struct rcar_sysc_info r8a774b1_sysc_info;
+extern const struct rcar_sysc_info r8a774c0_sysc_info;
+extern const struct rcar_sysc_info r8a774e1_sysc_info;
+extern const struct rcar_sysc_info r8a7779_sysc_info;
+extern const struct rcar_sysc_info r8a7790_sysc_info;
+extern const struct rcar_sysc_info r8a7791_sysc_info;
+extern const struct rcar_sysc_info r8a7792_sysc_info;
+extern const struct rcar_sysc_info r8a7794_sysc_info;
+extern struct rcar_sysc_info r8a7795_sysc_info;
+extern const struct rcar_sysc_info r8a77960_sysc_info;
+extern const struct rcar_sysc_info r8a77961_sysc_info;
+extern const struct rcar_sysc_info r8a77965_sysc_info;
+extern const struct rcar_sysc_info r8a77970_sysc_info;
+extern const struct rcar_sysc_info r8a77980_sysc_info;
+extern const struct rcar_sysc_info r8a77990_sysc_info;
+extern const struct rcar_sysc_info r8a77995_sysc_info;
+
+
+    /*
+     * Helpers for fixing up power area tables depending on SoC revision
+     */
+
+extern void rcar_sysc_nullify(struct rcar_sysc_area *areas,
+                             unsigned int num_areas, u8 id);
+
+#endif /* __SOC_RENESAS_RCAR_SYSC_H__ */
diff --git a/drivers/pmdomain/renesas/rmobile-sysc.c b/drivers/pmdomain/renesas/rmobile-sysc.c
new file mode 100644 (file)
index 0000000..912daad
--- /dev/null
@@ -0,0 +1,343 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rmobile power management support
+ *
+ * Copyright (C) 2012  Renesas Solutions Corp.
+ * Copyright (C) 2012  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ * Copyright (C) 2014  Glider bvba
+ *
+ * based on pm-sh7372.c
+ *  Copyright (C) 2011 Magnus Damm
+ */
+#include <linux/clk/renesas.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/pm.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+
+/* SYSC */
+#define SPDCR          0x08    /* SYS Power Down Control Register */
+#define SWUCR          0x14    /* SYS Wakeup Control Register */
+#define PSTR           0x80    /* Power Status Register */
+
+#define PSTR_RETRIES   100
+#define PSTR_DELAY_US  10
+
+struct rmobile_pm_domain {
+       struct generic_pm_domain genpd;
+       struct dev_power_governor *gov;
+       int (*suspend)(void);
+       void __iomem *base;
+       unsigned int bit_shift;
+};
+
+static inline
+struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d)
+{
+       return container_of(d, struct rmobile_pm_domain, genpd);
+}
+
+static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
+{
+       struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd);
+       unsigned int mask = BIT(rmobile_pd->bit_shift);
+       u32 val;
+
+       if (rmobile_pd->suspend) {
+               int ret = rmobile_pd->suspend();
+
+               if (ret)
+                       return ret;
+       }
+
+       if (readl(rmobile_pd->base + PSTR) & mask) {
+               writel(mask, rmobile_pd->base + SPDCR);
+
+               readl_poll_timeout_atomic(rmobile_pd->base + SPDCR, val,
+                                         !(val & mask), 0, PSTR_RETRIES);
+       }
+
+       pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", genpd->name, mask,
+                readl(rmobile_pd->base + PSTR));
+
+       return 0;
+}
+
+static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd)
+{
+       unsigned int val, mask = BIT(rmobile_pd->bit_shift);
+       int ret = 0;
+
+       if (readl(rmobile_pd->base + PSTR) & mask)
+               return ret;
+
+       writel(mask, rmobile_pd->base + SWUCR);
+
+       ret = readl_poll_timeout_atomic(rmobile_pd->base + SWUCR, val,
+                                       (val & mask), PSTR_DELAY_US,
+                                       PSTR_RETRIES * PSTR_DELAY_US);
+
+       pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
+                rmobile_pd->genpd.name, mask,
+                readl(rmobile_pd->base + PSTR));
+
+       return ret;
+}
+
+static int rmobile_pd_power_up(struct generic_pm_domain *genpd)
+{
+       return __rmobile_pd_power_up(to_rmobile_pd(genpd));
+}
+
+static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
+{
+       struct generic_pm_domain *genpd = &rmobile_pd->genpd;
+       struct dev_power_governor *gov = rmobile_pd->gov;
+
+       genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
+       genpd->attach_dev = cpg_mstp_attach_dev;
+       genpd->detach_dev = cpg_mstp_detach_dev;
+
+       if (!(genpd->flags & GENPD_FLAG_ALWAYS_ON)) {
+               genpd->power_off = rmobile_pd_power_down;
+               genpd->power_on = rmobile_pd_power_up;
+               __rmobile_pd_power_up(rmobile_pd);
+       }
+
+       pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
+}
+
+static int rmobile_pd_suspend_console(void)
+{
+       /*
+        * Serial consoles make use of SCIF hardware located in this domain,
+        * hence keep the power domain on if "no_console_suspend" is set.
+        */
+       return console_suspend_enabled ? 0 : -EBUSY;
+}
+
+enum pd_types {
+       PD_NORMAL,
+       PD_CPU,
+       PD_CONSOLE,
+       PD_DEBUG,
+       PD_MEMCTL,
+};
+
+#define MAX_NUM_SPECIAL_PDS    16
+
+static struct special_pd {
+       struct device_node *pd;
+       enum pd_types type;
+} special_pds[MAX_NUM_SPECIAL_PDS] __initdata;
+
+static unsigned int num_special_pds __initdata;
+
+static const struct of_device_id special_ids[] __initconst = {
+       { .compatible = "arm,coresight-etm3x", .data = (void *)PD_DEBUG },
+       { .compatible = "renesas,dbsc-r8a73a4", .data = (void *)PD_MEMCTL, },
+       { .compatible = "renesas,dbsc3-r8a7740", .data = (void *)PD_MEMCTL, },
+       { .compatible = "renesas,sbsc-sh73a0", .data = (void *)PD_MEMCTL, },
+       { /* sentinel */ },
+};
+
+static void __init add_special_pd(struct device_node *np, enum pd_types type)
+{
+       unsigned int i;
+       struct device_node *pd;
+
+       pd = of_parse_phandle(np, "power-domains", 0);
+       if (!pd)
+               return;
+
+       for (i = 0; i < num_special_pds; i++)
+               if (pd == special_pds[i].pd && type == special_pds[i].type) {
+                       of_node_put(pd);
+                       return;
+               }
+
+       if (num_special_pds == ARRAY_SIZE(special_pds)) {
+               pr_warn("Too many special PM domains\n");
+               of_node_put(pd);
+               return;
+       }
+
+       pr_debug("Special PM domain %pOFn type %d for %pOF\n", pd, type, np);
+
+       special_pds[num_special_pds].pd = pd;
+       special_pds[num_special_pds].type = type;
+       num_special_pds++;
+}
+
+static void __init get_special_pds(void)
+{
+       struct device_node *np;
+       const struct of_device_id *id;
+
+       /* PM domains containing CPUs */
+       for_each_of_cpu_node(np)
+               add_special_pd(np, PD_CPU);
+
+       /* PM domain containing console */
+       if (of_stdout)
+               add_special_pd(of_stdout, PD_CONSOLE);
+
+       /* PM domains containing other special devices */
+       for_each_matching_node_and_match(np, special_ids, &id)
+               add_special_pd(np, (enum pd_types)id->data);
+}
+
+static void __init put_special_pds(void)
+{
+       unsigned int i;
+
+       for (i = 0; i < num_special_pds; i++)
+               of_node_put(special_pds[i].pd);
+}
+
+static enum pd_types __init pd_type(const struct device_node *pd)
+{
+       unsigned int i;
+
+       for (i = 0; i < num_special_pds; i++)
+               if (pd == special_pds[i].pd)
+                       return special_pds[i].type;
+
+       return PD_NORMAL;
+}
+
+static void __init rmobile_setup_pm_domain(struct device_node *np,
+                                          struct rmobile_pm_domain *pd)
+{
+       const char *name = pd->genpd.name;
+
+       switch (pd_type(np)) {
+       case PD_CPU:
+               /*
+                * This domain contains the CPU core and therefore it should
+                * only be turned off if the CPU is not in use.
+                */
+               pr_debug("PM domain %s contains CPU\n", name);
+               pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
+               break;
+
+       case PD_CONSOLE:
+               pr_debug("PM domain %s contains serial console\n", name);
+               pd->gov = &pm_domain_always_on_gov;
+               pd->suspend = rmobile_pd_suspend_console;
+               break;
+
+       case PD_DEBUG:
+               /*
+                * This domain contains the Coresight-ETM hardware block and
+                * therefore it should only be turned off if the debug module
+                * is not in use.
+                */
+               pr_debug("PM domain %s contains Coresight-ETM\n", name);
+               pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
+               break;
+
+       case PD_MEMCTL:
+               /*
+                * This domain contains a memory-controller and therefore it
+                * should only be turned off if memory is not in use.
+                */
+               pr_debug("PM domain %s contains MEMCTL\n", name);
+               pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
+               break;
+
+       case PD_NORMAL:
+               if (pd->bit_shift == ~0) {
+                       /* Top-level always-on domain */
+                       pr_debug("PM domain %s is always-on domain\n", name);
+                       pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
+               }
+               break;
+       }
+
+       rmobile_init_pm_domain(pd);
+}
+
+static int __init rmobile_add_pm_domains(void __iomem *base,
+                                        struct device_node *parent,
+                                        struct generic_pm_domain *genpd_parent)
+{
+       struct device_node *np;
+
+       for_each_child_of_node(parent, np) {
+               struct rmobile_pm_domain *pd;
+               u32 idx = ~0;
+
+               if (of_property_read_u32(np, "reg", &idx)) {
+                       /* always-on domain */
+               }
+
+               pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+               if (!pd) {
+                       of_node_put(np);
+                       return -ENOMEM;
+               }
+
+               pd->genpd.name = np->name;
+               pd->base = base;
+               pd->bit_shift = idx;
+
+               rmobile_setup_pm_domain(np, pd);
+               if (genpd_parent)
+                       pm_genpd_add_subdomain(genpd_parent, &pd->genpd);
+               of_genpd_add_provider_simple(np, &pd->genpd);
+
+               rmobile_add_pm_domains(base, np, &pd->genpd);
+       }
+       return 0;
+}
+
+static int __init rmobile_init_pm_domains(void)
+{
+       struct device_node *np, *pmd;
+       bool scanned = false;
+       void __iomem *base;
+       int ret = 0;
+
+       for_each_compatible_node(np, NULL, "renesas,sysc-rmobile") {
+               base = of_iomap(np, 0);
+               if (!base) {
+                       pr_warn("%pOF cannot map reg 0\n", np);
+                       continue;
+               }
+
+               pmd = of_get_child_by_name(np, "pm-domains");
+               if (!pmd) {
+                       iounmap(base);
+                       pr_warn("%pOF lacks pm-domains node\n", np);
+                       continue;
+               }
+
+               if (!scanned) {
+                       /* Find PM domains containing special blocks */
+                       get_special_pds();
+                       scanned = true;
+               }
+
+               ret = rmobile_add_pm_domains(base, pmd, NULL);
+               of_node_put(pmd);
+               if (ret) {
+                       of_node_put(np);
+                       break;
+               }
+
+               fwnode_dev_initialized(of_fwnode_handle(np), true);
+       }
+
+       put_special_pds();
+
+       return ret;
+}
+
+core_initcall(rmobile_init_pm_domains);
diff --git a/drivers/pmdomain/rockchip/Makefile b/drivers/pmdomain/rockchip/Makefile
new file mode 100644 (file)
index 0000000..8fb9d88
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_ROCKCHIP_PM_DOMAINS)      += pm-domains.o
diff --git a/drivers/pmdomain/rockchip/pm-domains.c b/drivers/pmdomain/rockchip/pm-domains.c
new file mode 100644 (file)
index 0000000..d5d3ecb
--- /dev/null
@@ -0,0 +1,1396 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Rockchip Generic power domain support.
+ *
+ * Copyright (c) 2015 ROCKCHIP, Co. Ltd.
+ */
+
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_domain.h>
+#include <linux/of_address.h>
+#include <linux/of_clk.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <soc/rockchip/pm_domains.h>
+#include <dt-bindings/power/px30-power.h>
+#include <dt-bindings/power/rockchip,rv1126-power.h>
+#include <dt-bindings/power/rk3036-power.h>
+#include <dt-bindings/power/rk3066-power.h>
+#include <dt-bindings/power/rk3128-power.h>
+#include <dt-bindings/power/rk3188-power.h>
+#include <dt-bindings/power/rk3228-power.h>
+#include <dt-bindings/power/rk3288-power.h>
+#include <dt-bindings/power/rk3328-power.h>
+#include <dt-bindings/power/rk3366-power.h>
+#include <dt-bindings/power/rk3368-power.h>
+#include <dt-bindings/power/rk3399-power.h>
+#include <dt-bindings/power/rk3568-power.h>
+#include <dt-bindings/power/rk3588-power.h>
+
+struct rockchip_domain_info {
+       const char *name;
+       int pwr_mask;
+       int status_mask;
+       int req_mask;
+       int idle_mask;
+       int ack_mask;
+       bool active_wakeup;
+       int pwr_w_mask;
+       int req_w_mask;
+       int mem_status_mask;
+       int repair_status_mask;
+       u32 pwr_offset;
+       u32 mem_offset;
+       u32 req_offset;
+};
+
+struct rockchip_pmu_info {
+       u32 pwr_offset;
+       u32 status_offset;
+       u32 req_offset;
+       u32 idle_offset;
+       u32 ack_offset;
+       u32 mem_pwr_offset;
+       u32 chain_status_offset;
+       u32 mem_status_offset;
+       u32 repair_status_offset;
+
+       u32 core_pwrcnt_offset;
+       u32 gpu_pwrcnt_offset;
+
+       unsigned int core_power_transition_time;
+       unsigned int gpu_power_transition_time;
+
+       int num_domains;
+       const struct rockchip_domain_info *domain_info;
+};
+
+#define MAX_QOS_REGS_NUM       5
+#define QOS_PRIORITY           0x08
+#define QOS_MODE               0x0c
+#define QOS_BANDWIDTH          0x10
+#define QOS_SATURATION         0x14
+#define QOS_EXTCONTROL         0x18
+
+struct rockchip_pm_domain {
+       struct generic_pm_domain genpd;
+       const struct rockchip_domain_info *info;
+       struct rockchip_pmu *pmu;
+       int num_qos;
+       struct regmap **qos_regmap;
+       u32 *qos_save_regs[MAX_QOS_REGS_NUM];
+       int num_clks;
+       struct clk_bulk_data *clks;
+};
+
+struct rockchip_pmu {
+       struct device *dev;
+       struct regmap *regmap;
+       const struct rockchip_pmu_info *info;
+       struct mutex mutex; /* mutex lock for pmu */
+       struct genpd_onecell_data genpd_data;
+       struct generic_pm_domain *domains[];
+};
+
+#define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd)
+
+#define DOMAIN(_name, pwr, status, req, idle, ack, wakeup)     \
+{                                                      \
+       .name = _name,                          \
+       .pwr_mask = (pwr),                              \
+       .status_mask = (status),                        \
+       .req_mask = (req),                              \
+       .idle_mask = (idle),                            \
+       .ack_mask = (ack),                              \
+       .active_wakeup = (wakeup),                      \
+}
+
+#define DOMAIN_M(_name, pwr, status, req, idle, ack, wakeup)   \
+{                                                      \
+       .name = _name,                          \
+       .pwr_w_mask = (pwr) << 16,                      \
+       .pwr_mask = (pwr),                              \
+       .status_mask = (status),                        \
+       .req_w_mask = (req) << 16,                      \
+       .req_mask = (req),                              \
+       .idle_mask = (idle),                            \
+       .ack_mask = (ack),                              \
+       .active_wakeup = wakeup,                        \
+}
+
+#define DOMAIN_M_O_R(_name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, ack, wakeup)     \
+{                                                      \
+       .name = _name,                                  \
+       .pwr_offset = p_offset,                         \
+       .pwr_w_mask = (pwr) << 16,                      \
+       .pwr_mask = (pwr),                              \
+       .status_mask = (status),                        \
+       .mem_offset = m_offset,                         \
+       .mem_status_mask = (m_status),                  \
+       .repair_status_mask = (r_status),               \
+       .req_offset = r_offset,                         \
+       .req_w_mask = (req) << 16,                      \
+       .req_mask = (req),                              \
+       .idle_mask = (idle),                            \
+       .ack_mask = (ack),                              \
+       .active_wakeup = wakeup,                        \
+}
+
+#define DOMAIN_RK3036(_name, req, ack, idle, wakeup)           \
+{                                                      \
+       .name = _name,                          \
+       .req_mask = (req),                              \
+       .req_w_mask = (req) << 16,                      \
+       .ack_mask = (ack),                              \
+       .idle_mask = (idle),                            \
+       .active_wakeup = wakeup,                        \
+}
+
+#define DOMAIN_PX30(name, pwr, status, req, wakeup)            \
+       DOMAIN_M(name, pwr, status, req, (req) << 16, req, wakeup)
+
+#define DOMAIN_RV1126(name, pwr, req, idle, wakeup)            \
+       DOMAIN_M(name, pwr, pwr, req, idle, idle, wakeup)
+
+#define DOMAIN_RK3288(name, pwr, status, req, wakeup)          \
+       DOMAIN(name, pwr, status, req, req, (req) << 16, wakeup)
+
+#define DOMAIN_RK3328(name, pwr, status, req, wakeup)          \
+       DOMAIN_M(name, pwr, pwr, req, (req) << 10, req, wakeup)
+
+#define DOMAIN_RK3368(name, pwr, status, req, wakeup)          \
+       DOMAIN(name, pwr, status, req, (req) << 16, req, wakeup)
+
+#define DOMAIN_RK3399(name, pwr, status, req, wakeup)          \
+       DOMAIN(name, pwr, status, req, req, req, wakeup)
+
+#define DOMAIN_RK3568(name, pwr, req, wakeup)          \
+       DOMAIN_M(name, pwr, pwr, req, req, req, wakeup)
+
+/*
+ * Dynamic Memory Controller may need to coordinate with us -- see
+ * rockchip_pmu_block().
+ *
+ * dmc_pmu_mutex protects registration-time races, so DMC driver doesn't try to
+ * block() while we're initializing the PMU.
+ */
+static DEFINE_MUTEX(dmc_pmu_mutex);
+static struct rockchip_pmu *dmc_pmu;
+
+/*
+ * Block PMU transitions and make sure they don't interfere with ARM Trusted
+ * Firmware operations. There are two conflicts, noted in the comments below.
+ *
+ * Caller must unblock PMU transitions via rockchip_pmu_unblock().
+ */
+int rockchip_pmu_block(void)
+{
+       struct rockchip_pmu *pmu;
+       struct generic_pm_domain *genpd;
+       struct rockchip_pm_domain *pd;
+       int i, ret;
+
+       mutex_lock(&dmc_pmu_mutex);
+
+       /* No PMU (yet)? Then we just block rockchip_pmu_probe(). */
+       if (!dmc_pmu)
+               return 0;
+       pmu = dmc_pmu;
+
+       /*
+        * mutex blocks all idle transitions: we can't touch the
+        * PMU_BUS_IDLE_REQ (our ".idle_offset") register while ARM Trusted
+        * Firmware might be using it.
+        */
+       mutex_lock(&pmu->mutex);
+
+       /*
+        * Power domain clocks: Per Rockchip, we *must* keep certain clocks
+        * enabled for the duration of power-domain transitions. Most
+        * transitions are handled by this driver, but some cases (in
+        * particular, DRAM DVFS / memory-controller idle) must be handled by
+        * firmware. Firmware can handle most clock management via a special
+        * "ungate" register (PMU_CRU_GATEDIS_CON0), but unfortunately, this
+        * doesn't handle PLLs. We can assist this transition by doing the
+        * clock management on behalf of firmware.
+        */
+       for (i = 0; i < pmu->genpd_data.num_domains; i++) {
+               genpd = pmu->genpd_data.domains[i];
+               if (genpd) {
+                       pd = to_rockchip_pd(genpd);
+                       ret = clk_bulk_enable(pd->num_clks, pd->clks);
+                       if (ret < 0) {
+                               dev_err(pmu->dev,
+                                       "failed to enable clks for domain '%s': %d\n",
+                                       genpd->name, ret);
+                               goto err;
+                       }
+               }
+       }
+
+       return 0;
+
+err:
+       for (i = i - 1; i >= 0; i--) {
+               genpd = pmu->genpd_data.domains[i];
+               if (genpd) {
+                       pd = to_rockchip_pd(genpd);
+                       clk_bulk_disable(pd->num_clks, pd->clks);
+               }
+       }
+       mutex_unlock(&pmu->mutex);
+       mutex_unlock(&dmc_pmu_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(rockchip_pmu_block);
+
+/* Unblock PMU transitions. */
+void rockchip_pmu_unblock(void)
+{
+       struct rockchip_pmu *pmu;
+       struct generic_pm_domain *genpd;
+       struct rockchip_pm_domain *pd;
+       int i;
+
+       if (dmc_pmu) {
+               pmu = dmc_pmu;
+               for (i = 0; i < pmu->genpd_data.num_domains; i++) {
+                       genpd = pmu->genpd_data.domains[i];
+                       if (genpd) {
+                               pd = to_rockchip_pd(genpd);
+                               clk_bulk_disable(pd->num_clks, pd->clks);
+                       }
+               }
+
+               mutex_unlock(&pmu->mutex);
+       }
+
+       mutex_unlock(&dmc_pmu_mutex);
+}
+EXPORT_SYMBOL_GPL(rockchip_pmu_unblock);
+
+#define DOMAIN_RK3588(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, wakeup)  \
+       DOMAIN_M_O_R(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, idle, wakeup)
+
+static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
+{
+       struct rockchip_pmu *pmu = pd->pmu;
+       const struct rockchip_domain_info *pd_info = pd->info;
+       unsigned int val;
+
+       regmap_read(pmu->regmap, pmu->info->idle_offset, &val);
+       return (val & pd_info->idle_mask) == pd_info->idle_mask;
+}
+
+static unsigned int rockchip_pmu_read_ack(struct rockchip_pmu *pmu)
+{
+       unsigned int val;
+
+       regmap_read(pmu->regmap, pmu->info->ack_offset, &val);
+       return val;
+}
+
+static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
+                                        bool idle)
+{
+       const struct rockchip_domain_info *pd_info = pd->info;
+       struct generic_pm_domain *genpd = &pd->genpd;
+       struct rockchip_pmu *pmu = pd->pmu;
+       u32 pd_req_offset = pd_info->req_offset;
+       unsigned int target_ack;
+       unsigned int val;
+       bool is_idle;
+       int ret;
+
+       if (pd_info->req_mask == 0)
+               return 0;
+       else if (pd_info->req_w_mask)
+               regmap_write(pmu->regmap, pmu->info->req_offset + pd_req_offset,
+                            idle ? (pd_info->req_mask | pd_info->req_w_mask) :
+                            pd_info->req_w_mask);
+       else
+               regmap_update_bits(pmu->regmap, pmu->info->req_offset + pd_req_offset,
+                                  pd_info->req_mask, idle ? -1U : 0);
+
+       wmb();
+
+       /* Wait util idle_ack = 1 */
+       target_ack = idle ? pd_info->ack_mask : 0;
+       ret = readx_poll_timeout_atomic(rockchip_pmu_read_ack, pmu, val,
+                                       (val & pd_info->ack_mask) == target_ack,
+                                       0, 10000);
+       if (ret) {
+               dev_err(pmu->dev,
+                       "failed to get ack on domain '%s', val=0x%x\n",
+                       genpd->name, val);
+               return ret;
+       }
+
+       ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_idle, pd,
+                                       is_idle, is_idle == idle, 0, 10000);
+       if (ret) {
+               dev_err(pmu->dev,
+                       "failed to set idle on domain '%s', val=%d\n",
+                       genpd->name, is_idle);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd)
+{
+       int i;
+
+       for (i = 0; i < pd->num_qos; i++) {
+               regmap_read(pd->qos_regmap[i],
+                           QOS_PRIORITY,
+                           &pd->qos_save_regs[0][i]);
+               regmap_read(pd->qos_regmap[i],
+                           QOS_MODE,
+                           &pd->qos_save_regs[1][i]);
+               regmap_read(pd->qos_regmap[i],
+                           QOS_BANDWIDTH,
+                           &pd->qos_save_regs[2][i]);
+               regmap_read(pd->qos_regmap[i],
+                           QOS_SATURATION,
+                           &pd->qos_save_regs[3][i]);
+               regmap_read(pd->qos_regmap[i],
+                           QOS_EXTCONTROL,
+                           &pd->qos_save_regs[4][i]);
+       }
+       return 0;
+}
+
+static int rockchip_pmu_restore_qos(struct rockchip_pm_domain *pd)
+{
+       int i;
+
+       for (i = 0; i < pd->num_qos; i++) {
+               regmap_write(pd->qos_regmap[i],
+                            QOS_PRIORITY,
+                            pd->qos_save_regs[0][i]);
+               regmap_write(pd->qos_regmap[i],
+                            QOS_MODE,
+                            pd->qos_save_regs[1][i]);
+               regmap_write(pd->qos_regmap[i],
+                            QOS_BANDWIDTH,
+                            pd->qos_save_regs[2][i]);
+               regmap_write(pd->qos_regmap[i],
+                            QOS_SATURATION,
+                            pd->qos_save_regs[3][i]);
+               regmap_write(pd->qos_regmap[i],
+                            QOS_EXTCONTROL,
+                            pd->qos_save_regs[4][i]);
+       }
+
+       return 0;
+}
+
+static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
+{
+       struct rockchip_pmu *pmu = pd->pmu;
+       unsigned int val;
+
+       if (pd->info->repair_status_mask) {
+               regmap_read(pmu->regmap, pmu->info->repair_status_offset, &val);
+               /* 1'b1: power on, 1'b0: power off */
+               return val & pd->info->repair_status_mask;
+       }
+
+       /* check idle status for idle-only domains */
+       if (pd->info->status_mask == 0)
+               return !rockchip_pmu_domain_is_idle(pd);
+
+       regmap_read(pmu->regmap, pmu->info->status_offset, &val);
+
+       /* 1'b0: power on, 1'b1: power off */
+       return !(val & pd->info->status_mask);
+}
+
+static bool rockchip_pmu_domain_is_mem_on(struct rockchip_pm_domain *pd)
+{
+       struct rockchip_pmu *pmu = pd->pmu;
+       unsigned int val;
+
+       regmap_read(pmu->regmap,
+                   pmu->info->mem_status_offset + pd->info->mem_offset, &val);
+
+       /* 1'b0: power on, 1'b1: power off */
+       return !(val & pd->info->mem_status_mask);
+}
+
+static bool rockchip_pmu_domain_is_chain_on(struct rockchip_pm_domain *pd)
+{
+       struct rockchip_pmu *pmu = pd->pmu;
+       unsigned int val;
+
+       regmap_read(pmu->regmap,
+                   pmu->info->chain_status_offset + pd->info->mem_offset, &val);
+
+       /* 1'b1: power on, 1'b0: power off */
+       return val & pd->info->mem_status_mask;
+}
+
+static int rockchip_pmu_domain_mem_reset(struct rockchip_pm_domain *pd)
+{
+       struct rockchip_pmu *pmu = pd->pmu;
+       struct generic_pm_domain *genpd = &pd->genpd;
+       bool is_on;
+       int ret = 0;
+
+       ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_chain_on, pd, is_on,
+                                       is_on == true, 0, 10000);
+       if (ret) {
+               dev_err(pmu->dev,
+                       "failed to get chain status '%s', target_on=1, val=%d\n",
+                       genpd->name, is_on);
+               goto error;
+       }
+
+       udelay(20);
+
+       regmap_write(pmu->regmap, pmu->info->mem_pwr_offset + pd->info->pwr_offset,
+                    (pd->info->pwr_mask | pd->info->pwr_w_mask));
+       wmb();
+
+       ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_mem_on, pd, is_on,
+                                       is_on == false, 0, 10000);
+       if (ret) {
+               dev_err(pmu->dev,
+                       "failed to get mem status '%s', target_on=0, val=%d\n",
+                       genpd->name, is_on);
+               goto error;
+       }
+
+       regmap_write(pmu->regmap, pmu->info->mem_pwr_offset + pd->info->pwr_offset,
+                    pd->info->pwr_w_mask);
+       wmb();
+
+       ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_mem_on, pd, is_on,
+                                       is_on == true, 0, 10000);
+       if (ret) {
+               dev_err(pmu->dev,
+                       "failed to get mem status '%s', target_on=1, val=%d\n",
+                       genpd->name, is_on);
+       }
+
+error:
+       return ret;
+}
+
+static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
+                                            bool on)
+{
+       struct rockchip_pmu *pmu = pd->pmu;
+       struct generic_pm_domain *genpd = &pd->genpd;
+       u32 pd_pwr_offset = pd->info->pwr_offset;
+       bool is_on, is_mem_on = false;
+
+       if (pd->info->pwr_mask == 0)
+               return;
+
+       if (on && pd->info->mem_status_mask)
+               is_mem_on = rockchip_pmu_domain_is_mem_on(pd);
+
+       if (pd->info->pwr_w_mask)
+               regmap_write(pmu->regmap, pmu->info->pwr_offset + pd_pwr_offset,
+                            on ? pd->info->pwr_w_mask :
+                            (pd->info->pwr_mask | pd->info->pwr_w_mask));
+       else
+               regmap_update_bits(pmu->regmap, pmu->info->pwr_offset + pd_pwr_offset,
+                                  pd->info->pwr_mask, on ? 0 : -1U);
+
+       wmb();
+
+       if (is_mem_on && rockchip_pmu_domain_mem_reset(pd))
+               return;
+
+       if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
+                                     is_on == on, 0, 10000)) {
+               dev_err(pmu->dev,
+                       "failed to set domain '%s', val=%d\n",
+                       genpd->name, is_on);
+               return;
+       }
+}
+
+static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
+{
+       struct rockchip_pmu *pmu = pd->pmu;
+       int ret;
+
+       mutex_lock(&pmu->mutex);
+
+       if (rockchip_pmu_domain_is_on(pd) != power_on) {
+               ret = clk_bulk_enable(pd->num_clks, pd->clks);
+               if (ret < 0) {
+                       dev_err(pmu->dev, "failed to enable clocks\n");
+                       mutex_unlock(&pmu->mutex);
+                       return ret;
+               }
+
+               if (!power_on) {
+                       rockchip_pmu_save_qos(pd);
+
+                       /* if powering down, idle request to NIU first */
+                       rockchip_pmu_set_idle_request(pd, true);
+               }
+
+               rockchip_do_pmu_set_power_domain(pd, power_on);
+
+               if (power_on) {
+                       /* if powering up, leave idle mode */
+                       rockchip_pmu_set_idle_request(pd, false);
+
+                       rockchip_pmu_restore_qos(pd);
+               }
+
+               clk_bulk_disable(pd->num_clks, pd->clks);
+       }
+
+       mutex_unlock(&pmu->mutex);
+       return 0;
+}
+
+static int rockchip_pd_power_on(struct generic_pm_domain *domain)
+{
+       struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
+
+       return rockchip_pd_power(pd, true);
+}
+
+static int rockchip_pd_power_off(struct generic_pm_domain *domain)
+{
+       struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
+
+       return rockchip_pd_power(pd, false);
+}
+
+static int rockchip_pd_attach_dev(struct generic_pm_domain *genpd,
+                                 struct device *dev)
+{
+       struct clk *clk;
+       int i;
+       int error;
+
+       dev_dbg(dev, "attaching to power domain '%s'\n", genpd->name);
+
+       error = pm_clk_create(dev);
+       if (error) {
+               dev_err(dev, "pm_clk_create failed %d\n", error);
+               return error;
+       }
+
+       i = 0;
+       while ((clk = of_clk_get(dev->of_node, i++)) && !IS_ERR(clk)) {
+               dev_dbg(dev, "adding clock '%pC' to list of PM clocks\n", clk);
+               error = pm_clk_add_clk(dev, clk);
+               if (error) {
+                       dev_err(dev, "pm_clk_add_clk failed %d\n", error);
+                       clk_put(clk);
+                       pm_clk_destroy(dev);
+                       return error;
+               }
+       }
+
+       return 0;
+}
+
+static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd,
+                                  struct device *dev)
+{
+       dev_dbg(dev, "detaching from power domain '%s'\n", genpd->name);
+
+       pm_clk_destroy(dev);
+}
+
+static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
+                                     struct device_node *node)
+{
+       const struct rockchip_domain_info *pd_info;
+       struct rockchip_pm_domain *pd;
+       struct device_node *qos_node;
+       int i, j;
+       u32 id;
+       int error;
+
+       error = of_property_read_u32(node, "reg", &id);
+       if (error) {
+               dev_err(pmu->dev,
+                       "%pOFn: failed to retrieve domain id (reg): %d\n",
+                       node, error);
+               return -EINVAL;
+       }
+
+       if (id >= pmu->info->num_domains) {
+               dev_err(pmu->dev, "%pOFn: invalid domain id %d\n",
+                       node, id);
+               return -EINVAL;
+       }
+       /* RK3588 has domains with two parents (RKVDEC0/RKVDEC1) */
+       if (pmu->genpd_data.domains[id])
+               return 0;
+
+       pd_info = &pmu->info->domain_info[id];
+       if (!pd_info) {
+               dev_err(pmu->dev, "%pOFn: undefined domain id %d\n",
+                       node, id);
+               return -EINVAL;
+       }
+
+       pd = devm_kzalloc(pmu->dev, sizeof(*pd), GFP_KERNEL);
+       if (!pd)
+               return -ENOMEM;
+
+       pd->info = pd_info;
+       pd->pmu = pmu;
+
+       pd->num_clks = of_clk_get_parent_count(node);
+       if (pd->num_clks > 0) {
+               pd->clks = devm_kcalloc(pmu->dev, pd->num_clks,
+                                       sizeof(*pd->clks), GFP_KERNEL);
+               if (!pd->clks)
+                       return -ENOMEM;
+       } else {
+               dev_dbg(pmu->dev, "%pOFn: doesn't have clocks: %d\n",
+                       node, pd->num_clks);
+               pd->num_clks = 0;
+       }
+
+       for (i = 0; i < pd->num_clks; i++) {
+               pd->clks[i].clk = of_clk_get(node, i);
+               if (IS_ERR(pd->clks[i].clk)) {
+                       error = PTR_ERR(pd->clks[i].clk);
+                       dev_err(pmu->dev,
+                               "%pOFn: failed to get clk at index %d: %d\n",
+                               node, i, error);
+                       return error;
+               }
+       }
+
+       error = clk_bulk_prepare(pd->num_clks, pd->clks);
+       if (error)
+               goto err_put_clocks;
+
+       pd->num_qos = of_count_phandle_with_args(node, "pm_qos",
+                                                NULL);
+
+       if (pd->num_qos > 0) {
+               pd->qos_regmap = devm_kcalloc(pmu->dev, pd->num_qos,
+                                             sizeof(*pd->qos_regmap),
+                                             GFP_KERNEL);
+               if (!pd->qos_regmap) {
+                       error = -ENOMEM;
+                       goto err_unprepare_clocks;
+               }
+
+               for (j = 0; j < MAX_QOS_REGS_NUM; j++) {
+                       pd->qos_save_regs[j] = devm_kcalloc(pmu->dev,
+                                                           pd->num_qos,
+                                                           sizeof(u32),
+                                                           GFP_KERNEL);
+                       if (!pd->qos_save_regs[j]) {
+                               error = -ENOMEM;
+                               goto err_unprepare_clocks;
+                       }
+               }
+
+               for (j = 0; j < pd->num_qos; j++) {
+                       qos_node = of_parse_phandle(node, "pm_qos", j);
+                       if (!qos_node) {
+                               error = -ENODEV;
+                               goto err_unprepare_clocks;
+                       }
+                       pd->qos_regmap[j] = syscon_node_to_regmap(qos_node);
+                       if (IS_ERR(pd->qos_regmap[j])) {
+                               error = -ENODEV;
+                               of_node_put(qos_node);
+                               goto err_unprepare_clocks;
+                       }
+                       of_node_put(qos_node);
+               }
+       }
+
+       if (pd->info->name)
+               pd->genpd.name = pd->info->name;
+       else
+               pd->genpd.name = kbasename(node->full_name);
+       pd->genpd.power_off = rockchip_pd_power_off;
+       pd->genpd.power_on = rockchip_pd_power_on;
+       pd->genpd.attach_dev = rockchip_pd_attach_dev;
+       pd->genpd.detach_dev = rockchip_pd_detach_dev;
+       pd->genpd.flags = GENPD_FLAG_PM_CLK;
+       if (pd_info->active_wakeup)
+               pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
+       pm_genpd_init(&pd->genpd, NULL,
+                     !rockchip_pmu_domain_is_on(pd) ||
+                     (pd->info->mem_status_mask && !rockchip_pmu_domain_is_mem_on(pd)));
+
+       pmu->genpd_data.domains[id] = &pd->genpd;
+       return 0;
+
+err_unprepare_clocks:
+       clk_bulk_unprepare(pd->num_clks, pd->clks);
+err_put_clocks:
+       clk_bulk_put(pd->num_clks, pd->clks);
+       return error;
+}
+
+static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd)
+{
+       int ret;
+
+       /*
+        * We're in the error cleanup already, so we only complain,
+        * but won't emit another error on top of the original one.
+        */
+       ret = pm_genpd_remove(&pd->genpd);
+       if (ret < 0)
+               dev_err(pd->pmu->dev, "failed to remove domain '%s' : %d - state may be inconsistent\n",
+                       pd->genpd.name, ret);
+
+       clk_bulk_unprepare(pd->num_clks, pd->clks);
+       clk_bulk_put(pd->num_clks, pd->clks);
+
+       /* protect the zeroing of pm->num_clks */
+       mutex_lock(&pd->pmu->mutex);
+       pd->num_clks = 0;
+       mutex_unlock(&pd->pmu->mutex);
+
+       /* devm will free our memory */
+}
+
+static void rockchip_pm_domain_cleanup(struct rockchip_pmu *pmu)
+{
+       struct generic_pm_domain *genpd;
+       struct rockchip_pm_domain *pd;
+       int i;
+
+       for (i = 0; i < pmu->genpd_data.num_domains; i++) {
+               genpd = pmu->genpd_data.domains[i];
+               if (genpd) {
+                       pd = to_rockchip_pd(genpd);
+                       rockchip_pm_remove_one_domain(pd);
+               }
+       }
+
+       /* devm will free our memory */
+}
+
+static void rockchip_configure_pd_cnt(struct rockchip_pmu *pmu,
+                                     u32 domain_reg_offset,
+                                     unsigned int count)
+{
+       /* First configure domain power down transition count ... */
+       regmap_write(pmu->regmap, domain_reg_offset, count);
+       /* ... and then power up count. */
+       regmap_write(pmu->regmap, domain_reg_offset + 4, count);
+}
+
+static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu,
+                                    struct device_node *parent)
+{
+       struct device_node *np;
+       struct generic_pm_domain *child_domain, *parent_domain;
+       int error;
+
+       for_each_child_of_node(parent, np) {
+               u32 idx;
+
+               error = of_property_read_u32(parent, "reg", &idx);
+               if (error) {
+                       dev_err(pmu->dev,
+                               "%pOFn: failed to retrieve domain id (reg): %d\n",
+                               parent, error);
+                       goto err_out;
+               }
+               parent_domain = pmu->genpd_data.domains[idx];
+
+               error = rockchip_pm_add_one_domain(pmu, np);
+               if (error) {
+                       dev_err(pmu->dev, "failed to handle node %pOFn: %d\n",
+                               np, error);
+                       goto err_out;
+               }
+
+               error = of_property_read_u32(np, "reg", &idx);
+               if (error) {
+                       dev_err(pmu->dev,
+                               "%pOFn: failed to retrieve domain id (reg): %d\n",
+                               np, error);
+                       goto err_out;
+               }
+               child_domain = pmu->genpd_data.domains[idx];
+
+               error = pm_genpd_add_subdomain(parent_domain, child_domain);
+               if (error) {
+                       dev_err(pmu->dev, "%s failed to add subdomain %s: %d\n",
+                               parent_domain->name, child_domain->name, error);
+                       goto err_out;
+               } else {
+                       dev_dbg(pmu->dev, "%s add subdomain: %s\n",
+                               parent_domain->name, child_domain->name);
+               }
+
+               rockchip_pm_add_subdomain(pmu, np);
+       }
+
+       return 0;
+
+err_out:
+       of_node_put(np);
+       return error;
+}
+
+static int rockchip_pm_domain_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct device_node *node;
+       struct device *parent;
+       struct rockchip_pmu *pmu;
+       const struct of_device_id *match;
+       const struct rockchip_pmu_info *pmu_info;
+       int error;
+
+       if (!np) {
+               dev_err(dev, "device tree node not found\n");
+               return -ENODEV;
+       }
+
+       match = of_match_device(dev->driver->of_match_table, dev);
+       if (!match || !match->data) {
+               dev_err(dev, "missing pmu data\n");
+               return -EINVAL;
+       }
+
+       pmu_info = match->data;
+
+       pmu = devm_kzalloc(dev,
+                          struct_size(pmu, domains, pmu_info->num_domains),
+                          GFP_KERNEL);
+       if (!pmu)
+               return -ENOMEM;
+
+       pmu->dev = &pdev->dev;
+       mutex_init(&pmu->mutex);
+
+       pmu->info = pmu_info;
+
+       pmu->genpd_data.domains = pmu->domains;
+       pmu->genpd_data.num_domains = pmu_info->num_domains;
+
+       parent = dev->parent;
+       if (!parent) {
+               dev_err(dev, "no parent for syscon devices\n");
+               return -ENODEV;
+       }
+
+       pmu->regmap = syscon_node_to_regmap(parent->of_node);
+       if (IS_ERR(pmu->regmap)) {
+               dev_err(dev, "no regmap available\n");
+               return PTR_ERR(pmu->regmap);
+       }
+
+       /*
+        * Configure power up and down transition delays for CORE
+        * and GPU domains.
+        */
+       if (pmu_info->core_power_transition_time)
+               rockchip_configure_pd_cnt(pmu, pmu_info->core_pwrcnt_offset,
+                                       pmu_info->core_power_transition_time);
+       if (pmu_info->gpu_pwrcnt_offset)
+               rockchip_configure_pd_cnt(pmu, pmu_info->gpu_pwrcnt_offset,
+                                       pmu_info->gpu_power_transition_time);
+
+       error = -ENODEV;
+
+       /*
+        * Prevent any rockchip_pmu_block() from racing with the remainder of
+        * setup (clocks, register initialization).
+        */
+       mutex_lock(&dmc_pmu_mutex);
+
+       for_each_available_child_of_node(np, node) {
+               error = rockchip_pm_add_one_domain(pmu, node);
+               if (error) {
+                       dev_err(dev, "failed to handle node %pOFn: %d\n",
+                               node, error);
+                       of_node_put(node);
+                       goto err_out;
+               }
+
+               error = rockchip_pm_add_subdomain(pmu, node);
+               if (error < 0) {
+                       dev_err(dev, "failed to handle subdomain node %pOFn: %d\n",
+                               node, error);
+                       of_node_put(node);
+                       goto err_out;
+               }
+       }
+
+       if (error) {
+               dev_dbg(dev, "no power domains defined\n");
+               goto err_out;
+       }
+
+       error = of_genpd_add_provider_onecell(np, &pmu->genpd_data);
+       if (error) {
+               dev_err(dev, "failed to add provider: %d\n", error);
+               goto err_out;
+       }
+
+       /* We only expect one PMU. */
+       if (!WARN_ON_ONCE(dmc_pmu))
+               dmc_pmu = pmu;
+
+       mutex_unlock(&dmc_pmu_mutex);
+
+       return 0;
+
+err_out:
+       rockchip_pm_domain_cleanup(pmu);
+       mutex_unlock(&dmc_pmu_mutex);
+       return error;
+}
+
+static const struct rockchip_domain_info px30_pm_domains[] = {
+       [PX30_PD_USB]           = DOMAIN_PX30("usb",      BIT(5),  BIT(5),  BIT(10), false),
+       [PX30_PD_SDCARD]        = DOMAIN_PX30("sdcard",   BIT(8),  BIT(8),  BIT(9),  false),
+       [PX30_PD_GMAC]          = DOMAIN_PX30("gmac",     BIT(10), BIT(10), BIT(6),  false),
+       [PX30_PD_MMC_NAND]      = DOMAIN_PX30("mmc_nand", BIT(11), BIT(11), BIT(5),  false),
+       [PX30_PD_VPU]           = DOMAIN_PX30("vpu",      BIT(12), BIT(12), BIT(14), false),
+       [PX30_PD_VO]            = DOMAIN_PX30("vo",       BIT(13), BIT(13), BIT(7),  false),
+       [PX30_PD_VI]            = DOMAIN_PX30("vi",       BIT(14), BIT(14), BIT(8),  false),
+       [PX30_PD_GPU]           = DOMAIN_PX30("gpu",      BIT(15), BIT(15), BIT(2),  false),
+};
+
+static const struct rockchip_domain_info rv1126_pm_domains[] = {
+       [RV1126_PD_VEPU]        = DOMAIN_RV1126("vepu", BIT(2),  BIT(9),  BIT(9), false),
+       [RV1126_PD_VI]          = DOMAIN_RV1126("vi", BIT(4),  BIT(6),  BIT(6),  false),
+       [RV1126_PD_VO]          = DOMAIN_RV1126("vo", BIT(5),  BIT(7),  BIT(7),  false),
+       [RV1126_PD_ISPP]        = DOMAIN_RV1126("ispp", BIT(1), BIT(8), BIT(8),  false),
+       [RV1126_PD_VDPU]        = DOMAIN_RV1126("vdpu", BIT(3), BIT(10), BIT(10), false),
+       [RV1126_PD_NVM]         = DOMAIN_RV1126("nvm", BIT(7), BIT(11), BIT(11),  false),
+       [RV1126_PD_SDIO]        = DOMAIN_RV1126("sdio", BIT(8), BIT(13), BIT(13),  false),
+       [RV1126_PD_USB]         = DOMAIN_RV1126("usb", BIT(9), BIT(15), BIT(15),  false),
+};
+
+static const struct rockchip_domain_info rk3036_pm_domains[] = {
+       [RK3036_PD_MSCH]        = DOMAIN_RK3036("msch", BIT(14), BIT(23), BIT(30), true),
+       [RK3036_PD_CORE]        = DOMAIN_RK3036("core", BIT(13), BIT(17), BIT(24), false),
+       [RK3036_PD_PERI]        = DOMAIN_RK3036("peri", BIT(12), BIT(18), BIT(25), false),
+       [RK3036_PD_VIO]         = DOMAIN_RK3036("vio",  BIT(11), BIT(19), BIT(26), false),
+       [RK3036_PD_VPU]         = DOMAIN_RK3036("vpu",  BIT(10), BIT(20), BIT(27), false),
+       [RK3036_PD_GPU]         = DOMAIN_RK3036("gpu",  BIT(9),  BIT(21), BIT(28), false),
+       [RK3036_PD_SYS]         = DOMAIN_RK3036("sys",  BIT(8),  BIT(22), BIT(29), false),
+};
+
+static const struct rockchip_domain_info rk3066_pm_domains[] = {
+       [RK3066_PD_GPU]         = DOMAIN("gpu",   BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false),
+       [RK3066_PD_VIDEO]       = DOMAIN("video", BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false),
+       [RK3066_PD_VIO]         = DOMAIN("vio",   BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false),
+       [RK3066_PD_PERI]        = DOMAIN("peri",  BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false),
+       [RK3066_PD_CPU]         = DOMAIN("cpu",   0,      BIT(5), BIT(1), BIT(26), BIT(31), false),
+};
+
+static const struct rockchip_domain_info rk3128_pm_domains[] = {
+       [RK3128_PD_CORE]        = DOMAIN_RK3288("core",  BIT(0), BIT(0), BIT(4), false),
+       [RK3128_PD_MSCH]        = DOMAIN_RK3288("msch",  0,      0,      BIT(6), true),
+       [RK3128_PD_VIO]         = DOMAIN_RK3288("vio",   BIT(3), BIT(3), BIT(2), false),
+       [RK3128_PD_VIDEO]       = DOMAIN_RK3288("video", BIT(2), BIT(2), BIT(1), false),
+       [RK3128_PD_GPU]         = DOMAIN_RK3288("gpu",   BIT(1), BIT(1), BIT(3), false),
+};
+
+static const struct rockchip_domain_info rk3188_pm_domains[] = {
+       [RK3188_PD_GPU]         = DOMAIN("gpu",   BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false),
+       [RK3188_PD_VIDEO]       = DOMAIN("video", BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false),
+       [RK3188_PD_VIO]         = DOMAIN("vio",   BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false),
+       [RK3188_PD_PERI]        = DOMAIN("peri",  BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false),
+       [RK3188_PD_CPU]         = DOMAIN("cpu",   BIT(5), BIT(5), BIT(1), BIT(26), BIT(31), false),
+};
+
+static const struct rockchip_domain_info rk3228_pm_domains[] = {
+       [RK3228_PD_CORE]        = DOMAIN_RK3036("core", BIT(0),  BIT(0),  BIT(16), true),
+       [RK3228_PD_MSCH]        = DOMAIN_RK3036("msch", BIT(1),  BIT(1),  BIT(17), true),
+       [RK3228_PD_BUS]         = DOMAIN_RK3036("bus",  BIT(2),  BIT(2),  BIT(18), true),
+       [RK3228_PD_SYS]         = DOMAIN_RK3036("sys",  BIT(3),  BIT(3),  BIT(19), true),
+       [RK3228_PD_VIO]         = DOMAIN_RK3036("vio",  BIT(4),  BIT(4),  BIT(20), false),
+       [RK3228_PD_VOP]         = DOMAIN_RK3036("vop",  BIT(5),  BIT(5),  BIT(21), false),
+       [RK3228_PD_VPU]         = DOMAIN_RK3036("vpu",  BIT(6),  BIT(6),  BIT(22), false),
+       [RK3228_PD_RKVDEC]      = DOMAIN_RK3036("vdec", BIT(7),  BIT(7),  BIT(23), false),
+       [RK3228_PD_GPU]         = DOMAIN_RK3036("gpu",  BIT(8),  BIT(8),  BIT(24), false),
+       [RK3228_PD_PERI]        = DOMAIN_RK3036("peri", BIT(9),  BIT(9),  BIT(25), true),
+       [RK3228_PD_GMAC]        = DOMAIN_RK3036("gmac", BIT(10), BIT(10), BIT(26), false),
+};
+
+static const struct rockchip_domain_info rk3288_pm_domains[] = {
+       [RK3288_PD_VIO]         = DOMAIN_RK3288("vio",   BIT(7),  BIT(7),  BIT(4), false),
+       [RK3288_PD_HEVC]        = DOMAIN_RK3288("hevc",  BIT(14), BIT(10), BIT(9), false),
+       [RK3288_PD_VIDEO]       = DOMAIN_RK3288("video", BIT(8),  BIT(8),  BIT(3), false),
+       [RK3288_PD_GPU]         = DOMAIN_RK3288("gpu",   BIT(9),  BIT(9),  BIT(2), false),
+};
+
+static const struct rockchip_domain_info rk3328_pm_domains[] = {
+       [RK3328_PD_CORE]        = DOMAIN_RK3328("core",  0, BIT(0), BIT(0), false),
+       [RK3328_PD_GPU]         = DOMAIN_RK3328("gpu",   0, BIT(1), BIT(1), false),
+       [RK3328_PD_BUS]         = DOMAIN_RK3328("bus",   0, BIT(2), BIT(2), true),
+       [RK3328_PD_MSCH]        = DOMAIN_RK3328("msch",  0, BIT(3), BIT(3), true),
+       [RK3328_PD_PERI]        = DOMAIN_RK3328("peri",  0, BIT(4), BIT(4), true),
+       [RK3328_PD_VIDEO]       = DOMAIN_RK3328("video", 0, BIT(5), BIT(5), false),
+       [RK3328_PD_HEVC]        = DOMAIN_RK3328("hevc",  0, BIT(6), BIT(6), false),
+       [RK3328_PD_VIO]         = DOMAIN_RK3328("vio",   0, BIT(8), BIT(8), false),
+       [RK3328_PD_VPU]         = DOMAIN_RK3328("vpu",   0, BIT(9), BIT(9), false),
+};
+
+static const struct rockchip_domain_info rk3366_pm_domains[] = {
+       [RK3366_PD_PERI]        = DOMAIN_RK3368("peri",   BIT(10), BIT(10), BIT(6), true),
+       [RK3366_PD_VIO]         = DOMAIN_RK3368("vio",    BIT(14), BIT(14), BIT(8), false),
+       [RK3366_PD_VIDEO]       = DOMAIN_RK3368("video",  BIT(13), BIT(13), BIT(7), false),
+       [RK3366_PD_RKVDEC]      = DOMAIN_RK3368("vdec",   BIT(11), BIT(11), BIT(7), false),
+       [RK3366_PD_WIFIBT]      = DOMAIN_RK3368("wifibt", BIT(8),  BIT(8),  BIT(9), false),
+       [RK3366_PD_VPU]         = DOMAIN_RK3368("vpu",    BIT(12), BIT(12), BIT(7), false),
+       [RK3366_PD_GPU]         = DOMAIN_RK3368("gpu",    BIT(15), BIT(15), BIT(2), false),
+};
+
+static const struct rockchip_domain_info rk3368_pm_domains[] = {
+       [RK3368_PD_PERI]        = DOMAIN_RK3368("peri",  BIT(13), BIT(12), BIT(6), true),
+       [RK3368_PD_VIO]         = DOMAIN_RK3368("vio",   BIT(15), BIT(14), BIT(8), false),
+       [RK3368_PD_VIDEO]       = DOMAIN_RK3368("video", BIT(14), BIT(13), BIT(7), false),
+       [RK3368_PD_GPU_0]       = DOMAIN_RK3368("gpu_0", BIT(16), BIT(15), BIT(2), false),
+       [RK3368_PD_GPU_1]       = DOMAIN_RK3368("gpu_1", BIT(17), BIT(16), BIT(2), false),
+};
+
+static const struct rockchip_domain_info rk3399_pm_domains[] = {
+       [RK3399_PD_TCPD0]       = DOMAIN_RK3399("tcpd0",     BIT(8),  BIT(8),  0,       false),
+       [RK3399_PD_TCPD1]       = DOMAIN_RK3399("tcpd1",     BIT(9),  BIT(9),  0,       false),
+       [RK3399_PD_CCI]         = DOMAIN_RK3399("cci",       BIT(10), BIT(10), 0,       true),
+       [RK3399_PD_CCI0]        = DOMAIN_RK3399("cci0",      0,       0,       BIT(15), true),
+       [RK3399_PD_CCI1]        = DOMAIN_RK3399("cci1",      0,       0,       BIT(16), true),
+       [RK3399_PD_PERILP]      = DOMAIN_RK3399("perilp",    BIT(11), BIT(11), BIT(1),  true),
+       [RK3399_PD_PERIHP]      = DOMAIN_RK3399("perihp",    BIT(12), BIT(12), BIT(2),  true),
+       [RK3399_PD_CENTER]      = DOMAIN_RK3399("center",    BIT(13), BIT(13), BIT(14), true),
+       [RK3399_PD_VIO]         = DOMAIN_RK3399("vio",       BIT(14), BIT(14), BIT(17), false),
+       [RK3399_PD_GPU]         = DOMAIN_RK3399("gpu",       BIT(15), BIT(15), BIT(0),  false),
+       [RK3399_PD_VCODEC]      = DOMAIN_RK3399("vcodec",    BIT(16), BIT(16), BIT(3),  false),
+       [RK3399_PD_VDU]         = DOMAIN_RK3399("vdu",       BIT(17), BIT(17), BIT(4),  false),
+       [RK3399_PD_RGA]         = DOMAIN_RK3399("rga",       BIT(18), BIT(18), BIT(5),  false),
+       [RK3399_PD_IEP]         = DOMAIN_RK3399("iep",       BIT(19), BIT(19), BIT(6),  false),
+       [RK3399_PD_VO]          = DOMAIN_RK3399("vo",        BIT(20), BIT(20), 0,       false),
+       [RK3399_PD_VOPB]        = DOMAIN_RK3399("vopb",      0,       0,       BIT(7),  false),
+       [RK3399_PD_VOPL]        = DOMAIN_RK3399("vopl",      0,       0,       BIT(8),  false),
+       [RK3399_PD_ISP0]        = DOMAIN_RK3399("isp0",      BIT(22), BIT(22), BIT(9),  false),
+       [RK3399_PD_ISP1]        = DOMAIN_RK3399("isp1",      BIT(23), BIT(23), BIT(10), false),
+       [RK3399_PD_HDCP]        = DOMAIN_RK3399("hdcp",      BIT(24), BIT(24), BIT(11), false),
+       [RK3399_PD_GMAC]        = DOMAIN_RK3399("gmac",      BIT(25), BIT(25), BIT(23), true),
+       [RK3399_PD_EMMC]        = DOMAIN_RK3399("emmc",      BIT(26), BIT(26), BIT(24), true),
+       [RK3399_PD_USB3]        = DOMAIN_RK3399("usb3",      BIT(27), BIT(27), BIT(12), true),
+       [RK3399_PD_EDP]         = DOMAIN_RK3399("edp",       BIT(28), BIT(28), BIT(22), false),
+       [RK3399_PD_GIC]         = DOMAIN_RK3399("gic",       BIT(29), BIT(29), BIT(27), true),
+       [RK3399_PD_SD]          = DOMAIN_RK3399("sd",        BIT(30), BIT(30), BIT(28), true),
+       [RK3399_PD_SDIOAUDIO]   = DOMAIN_RK3399("sdioaudio", BIT(31), BIT(31), BIT(29), true),
+};
+
+static const struct rockchip_domain_info rk3568_pm_domains[] = {
+       [RK3568_PD_NPU]         = DOMAIN_RK3568("npu",  BIT(1), BIT(2),  false),
+       [RK3568_PD_GPU]         = DOMAIN_RK3568("gpu",  BIT(0), BIT(1),  false),
+       [RK3568_PD_VI]          = DOMAIN_RK3568("vi",   BIT(6), BIT(3),  false),
+       [RK3568_PD_VO]          = DOMAIN_RK3568("vo",   BIT(7), BIT(4),  false),
+       [RK3568_PD_RGA]         = DOMAIN_RK3568("rga",  BIT(5), BIT(5),  false),
+       [RK3568_PD_VPU]         = DOMAIN_RK3568("vpu",  BIT(2), BIT(6),  false),
+       [RK3568_PD_RKVDEC]      = DOMAIN_RK3568("vdec", BIT(4), BIT(8),  false),
+       [RK3568_PD_RKVENC]      = DOMAIN_RK3568("venc", BIT(3), BIT(7),  false),
+       [RK3568_PD_PIPE]        = DOMAIN_RK3568("pipe", BIT(8), BIT(11), false),
+};
+
+static const struct rockchip_domain_info rk3588_pm_domains[] = {
+       [RK3588_PD_GPU]         = DOMAIN_RK3588("gpu",     0x0, BIT(0),  0,       0x0, 0,       BIT(1),  0x0, BIT(0),  BIT(0),  false),
+       [RK3588_PD_NPU]         = DOMAIN_RK3588("npu",     0x0, BIT(1),  BIT(1),  0x0, 0,       0,       0x0, 0,       0,       false),
+       [RK3588_PD_VCODEC]      = DOMAIN_RK3588("vcodec",  0x0, BIT(2),  BIT(2),  0x0, 0,       0,       0x0, 0,       0,       false),
+       [RK3588_PD_NPUTOP]      = DOMAIN_RK3588("nputop",  0x0, BIT(3),  0,       0x0, BIT(11), BIT(2),  0x0, BIT(1),  BIT(1),  false),
+       [RK3588_PD_NPU1]        = DOMAIN_RK3588("npu1",    0x0, BIT(4),  0,       0x0, BIT(12), BIT(3),  0x0, BIT(2),  BIT(2),  false),
+       [RK3588_PD_NPU2]        = DOMAIN_RK3588("npu2",    0x0, BIT(5),  0,       0x0, BIT(13), BIT(4),  0x0, BIT(3),  BIT(3),  false),
+       [RK3588_PD_VENC0]       = DOMAIN_RK3588("venc0",   0x0, BIT(6),  0,       0x0, BIT(14), BIT(5),  0x0, BIT(4),  BIT(4),  false),
+       [RK3588_PD_VENC1]       = DOMAIN_RK3588("venc1",   0x0, BIT(7),  0,       0x0, BIT(15), BIT(6),  0x0, BIT(5),  BIT(5),  false),
+       [RK3588_PD_RKVDEC0]     = DOMAIN_RK3588("rkvdec0", 0x0, BIT(8),  0,       0x0, BIT(16), BIT(7),  0x0, BIT(6),  BIT(6),  false),
+       [RK3588_PD_RKVDEC1]     = DOMAIN_RK3588("rkvdec1", 0x0, BIT(9),  0,       0x0, BIT(17), BIT(8),  0x0, BIT(7),  BIT(7),  false),
+       [RK3588_PD_VDPU]        = DOMAIN_RK3588("vdpu",    0x0, BIT(10), 0,       0x0, BIT(18), BIT(9),  0x0, BIT(8),  BIT(8),  false),
+       [RK3588_PD_RGA30]       = DOMAIN_RK3588("rga30",   0x0, BIT(11), 0,       0x0, BIT(19), BIT(10), 0x0, 0,       0,       false),
+       [RK3588_PD_AV1]         = DOMAIN_RK3588("av1",     0x0, BIT(12), 0,       0x0, BIT(20), BIT(11), 0x0, BIT(9),  BIT(9),  false),
+       [RK3588_PD_VI]          = DOMAIN_RK3588("vi",      0x0, BIT(13), 0,       0x0, BIT(21), BIT(12), 0x0, BIT(10), BIT(10), false),
+       [RK3588_PD_FEC]         = DOMAIN_RK3588("fec",     0x0, BIT(14), 0,       0x0, BIT(22), BIT(13), 0x0, 0,       0,       false),
+       [RK3588_PD_ISP1]        = DOMAIN_RK3588("isp1",    0x0, BIT(15), 0,       0x0, BIT(23), BIT(14), 0x0, BIT(11), BIT(11), false),
+       [RK3588_PD_RGA31]       = DOMAIN_RK3588("rga31",   0x4, BIT(0),  0,       0x0, BIT(24), BIT(15), 0x0, BIT(12), BIT(12), false),
+       [RK3588_PD_VOP]         = DOMAIN_RK3588("vop",     0x4, BIT(1),  0,       0x0, BIT(25), BIT(16), 0x0, BIT(13) | BIT(14), BIT(13) | BIT(14), false),
+       [RK3588_PD_VO0]         = DOMAIN_RK3588("vo0",     0x4, BIT(2),  0,       0x0, BIT(26), BIT(17), 0x0, BIT(15), BIT(15), false),
+       [RK3588_PD_VO1]         = DOMAIN_RK3588("vo1",     0x4, BIT(3),  0,       0x0, BIT(27), BIT(18), 0x4, BIT(0),  BIT(16), false),
+       [RK3588_PD_AUDIO]       = DOMAIN_RK3588("audio",   0x4, BIT(4),  0,       0x0, BIT(28), BIT(19), 0x4, BIT(1),  BIT(17), false),
+       [RK3588_PD_PHP]         = DOMAIN_RK3588("php",     0x4, BIT(5),  0,       0x0, BIT(29), BIT(20), 0x4, BIT(5),  BIT(21), false),
+       [RK3588_PD_GMAC]        = DOMAIN_RK3588("gmac",    0x4, BIT(6),  0,       0x0, BIT(30), BIT(21), 0x0, 0,       0,       false),
+       [RK3588_PD_PCIE]        = DOMAIN_RK3588("pcie",    0x4, BIT(7),  0,       0x0, BIT(31), BIT(22), 0x0, 0,       0,       true),
+       [RK3588_PD_NVM]         = DOMAIN_RK3588("nvm",     0x4, BIT(8),  BIT(24), 0x4, 0,       0,       0x4, BIT(2),  BIT(18), false),
+       [RK3588_PD_NVM0]        = DOMAIN_RK3588("nvm0",    0x4, BIT(9),  0,       0x4, BIT(1),  BIT(23), 0x0, 0,       0,       false),
+       [RK3588_PD_SDIO]        = DOMAIN_RK3588("sdio",    0x4, BIT(10), 0,       0x4, BIT(2),  BIT(24), 0x4, BIT(3),  BIT(19), false),
+       [RK3588_PD_USB]         = DOMAIN_RK3588("usb",     0x4, BIT(11), 0,       0x4, BIT(3),  BIT(25), 0x4, BIT(4),  BIT(20), true),
+       [RK3588_PD_SDMMC]       = DOMAIN_RK3588("sdmmc",   0x4, BIT(13), 0,       0x4, BIT(5),  BIT(26), 0x0, 0,       0,       false),
+};
+
+static const struct rockchip_pmu_info px30_pmu = {
+       .pwr_offset = 0x18,
+       .status_offset = 0x20,
+       .req_offset = 0x64,
+       .idle_offset = 0x6c,
+       .ack_offset = 0x6c,
+
+       .num_domains = ARRAY_SIZE(px30_pm_domains),
+       .domain_info = px30_pm_domains,
+};
+
+static const struct rockchip_pmu_info rk3036_pmu = {
+       .req_offset = 0x148,
+       .idle_offset = 0x14c,
+       .ack_offset = 0x14c,
+
+       .num_domains = ARRAY_SIZE(rk3036_pm_domains),
+       .domain_info = rk3036_pm_domains,
+};
+
+static const struct rockchip_pmu_info rk3066_pmu = {
+       .pwr_offset = 0x08,
+       .status_offset = 0x0c,
+       .req_offset = 0x38, /* PMU_MISC_CON1 */
+       .idle_offset = 0x0c,
+       .ack_offset = 0x0c,
+
+       .num_domains = ARRAY_SIZE(rk3066_pm_domains),
+       .domain_info = rk3066_pm_domains,
+};
+
+static const struct rockchip_pmu_info rk3128_pmu = {
+       .pwr_offset = 0x04,
+       .status_offset = 0x08,
+       .req_offset = 0x0c,
+       .idle_offset = 0x10,
+       .ack_offset = 0x10,
+
+       .num_domains = ARRAY_SIZE(rk3128_pm_domains),
+       .domain_info = rk3128_pm_domains,
+};
+
+static const struct rockchip_pmu_info rk3188_pmu = {
+       .pwr_offset = 0x08,
+       .status_offset = 0x0c,
+       .req_offset = 0x38, /* PMU_MISC_CON1 */
+       .idle_offset = 0x0c,
+       .ack_offset = 0x0c,
+
+       .num_domains = ARRAY_SIZE(rk3188_pm_domains),
+       .domain_info = rk3188_pm_domains,
+};
+
+static const struct rockchip_pmu_info rk3228_pmu = {
+       .req_offset = 0x40c,
+       .idle_offset = 0x488,
+       .ack_offset = 0x488,
+
+       .num_domains = ARRAY_SIZE(rk3228_pm_domains),
+       .domain_info = rk3228_pm_domains,
+};
+
+static const struct rockchip_pmu_info rk3288_pmu = {
+       .pwr_offset = 0x08,
+       .status_offset = 0x0c,
+       .req_offset = 0x10,
+       .idle_offset = 0x14,
+       .ack_offset = 0x14,
+
+       .core_pwrcnt_offset = 0x34,
+       .gpu_pwrcnt_offset = 0x3c,
+
+       .core_power_transition_time = 24, /* 1us */
+       .gpu_power_transition_time = 24, /* 1us */
+
+       .num_domains = ARRAY_SIZE(rk3288_pm_domains),
+       .domain_info = rk3288_pm_domains,
+};
+
+static const struct rockchip_pmu_info rk3328_pmu = {
+       .req_offset = 0x414,
+       .idle_offset = 0x484,
+       .ack_offset = 0x484,
+
+       .num_domains = ARRAY_SIZE(rk3328_pm_domains),
+       .domain_info = rk3328_pm_domains,
+};
+
+static const struct rockchip_pmu_info rk3366_pmu = {
+       .pwr_offset = 0x0c,
+       .status_offset = 0x10,
+       .req_offset = 0x3c,
+       .idle_offset = 0x40,
+       .ack_offset = 0x40,
+
+       .core_pwrcnt_offset = 0x48,
+       .gpu_pwrcnt_offset = 0x50,
+
+       .core_power_transition_time = 24,
+       .gpu_power_transition_time = 24,
+
+       .num_domains = ARRAY_SIZE(rk3366_pm_domains),
+       .domain_info = rk3366_pm_domains,
+};
+
+static const struct rockchip_pmu_info rk3368_pmu = {
+       .pwr_offset = 0x0c,
+       .status_offset = 0x10,
+       .req_offset = 0x3c,
+       .idle_offset = 0x40,
+       .ack_offset = 0x40,
+
+       .core_pwrcnt_offset = 0x48,
+       .gpu_pwrcnt_offset = 0x50,
+
+       .core_power_transition_time = 24,
+       .gpu_power_transition_time = 24,
+
+       .num_domains = ARRAY_SIZE(rk3368_pm_domains),
+       .domain_info = rk3368_pm_domains,
+};
+
+static const struct rockchip_pmu_info rk3399_pmu = {
+       .pwr_offset = 0x14,
+       .status_offset = 0x18,
+       .req_offset = 0x60,
+       .idle_offset = 0x64,
+       .ack_offset = 0x68,
+
+       /* ARM Trusted Firmware manages power transition times */
+
+       .num_domains = ARRAY_SIZE(rk3399_pm_domains),
+       .domain_info = rk3399_pm_domains,
+};
+
+static const struct rockchip_pmu_info rk3568_pmu = {
+       .pwr_offset = 0xa0,
+       .status_offset = 0x98,
+       .req_offset = 0x50,
+       .idle_offset = 0x68,
+       .ack_offset = 0x60,
+
+       .num_domains = ARRAY_SIZE(rk3568_pm_domains),
+       .domain_info = rk3568_pm_domains,
+};
+
+static const struct rockchip_pmu_info rk3588_pmu = {
+       .pwr_offset = 0x14c,
+       .status_offset = 0x180,
+       .req_offset = 0x10c,
+       .idle_offset = 0x120,
+       .ack_offset = 0x118,
+       .mem_pwr_offset = 0x1a0,
+       .chain_status_offset = 0x1f0,
+       .mem_status_offset = 0x1f8,
+       .repair_status_offset = 0x290,
+
+       .num_domains = ARRAY_SIZE(rk3588_pm_domains),
+       .domain_info = rk3588_pm_domains,
+};
+
+static const struct rockchip_pmu_info rv1126_pmu = {
+       .pwr_offset = 0x110,
+       .status_offset = 0x108,
+       .req_offset = 0xc0,
+       .idle_offset = 0xd8,
+       .ack_offset = 0xd0,
+
+       .num_domains = ARRAY_SIZE(rv1126_pm_domains),
+       .domain_info = rv1126_pm_domains,
+};
+
+static const struct of_device_id rockchip_pm_domain_dt_match[] = {
+       {
+               .compatible = "rockchip,px30-power-controller",
+               .data = (void *)&px30_pmu,
+       },
+       {
+               .compatible = "rockchip,rk3036-power-controller",
+               .data = (void *)&rk3036_pmu,
+       },
+       {
+               .compatible = "rockchip,rk3066-power-controller",
+               .data = (void *)&rk3066_pmu,
+       },
+       {
+               .compatible = "rockchip,rk3128-power-controller",
+               .data = (void *)&rk3128_pmu,
+       },
+       {
+               .compatible = "rockchip,rk3188-power-controller",
+               .data = (void *)&rk3188_pmu,
+       },
+       {
+               .compatible = "rockchip,rk3228-power-controller",
+               .data = (void *)&rk3228_pmu,
+       },
+       {
+               .compatible = "rockchip,rk3288-power-controller",
+               .data = (void *)&rk3288_pmu,
+       },
+       {
+               .compatible = "rockchip,rk3328-power-controller",
+               .data = (void *)&rk3328_pmu,
+       },
+       {
+               .compatible = "rockchip,rk3366-power-controller",
+               .data = (void *)&rk3366_pmu,
+       },
+       {
+               .compatible = "rockchip,rk3368-power-controller",
+               .data = (void *)&rk3368_pmu,
+       },
+       {
+               .compatible = "rockchip,rk3399-power-controller",
+               .data = (void *)&rk3399_pmu,
+       },
+       {
+               .compatible = "rockchip,rk3568-power-controller",
+               .data = (void *)&rk3568_pmu,
+       },
+       {
+               .compatible = "rockchip,rk3588-power-controller",
+               .data = (void *)&rk3588_pmu,
+       },
+       {
+               .compatible = "rockchip,rv1126-power-controller",
+               .data = (void *)&rv1126_pmu,
+       },
+       { /* sentinel */ },
+};
+
+static struct platform_driver rockchip_pm_domain_driver = {
+       .probe = rockchip_pm_domain_probe,
+       .driver = {
+               .name   = "rockchip-pm-domain",
+               .of_match_table = rockchip_pm_domain_dt_match,
+               /*
+                * We can't forcibly eject devices from the power
+                * domain, so we can't really remove power domains
+                * once they were added.
+                */
+               .suppress_bind_attrs = true,
+       },
+};
+
+static int __init rockchip_pm_domain_drv_register(void)
+{
+       return platform_driver_register(&rockchip_pm_domain_driver);
+}
+postcore_initcall(rockchip_pm_domain_drv_register);
diff --git a/drivers/pmdomain/samsung/Makefile b/drivers/pmdomain/samsung/Makefile
new file mode 100644 (file)
index 0000000..397aa59
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_EXYNOS_PM_DOMAINS)                += exynos-pm-domains.o
diff --git a/drivers/pmdomain/samsung/exynos-pm-domains.c b/drivers/pmdomain/samsung/exynos-pm-domains.c
new file mode 100644 (file)
index 0000000..9b502e8
--- /dev/null
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Exynos Generic power domain support.
+//
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//             http://www.samsung.com
+//
+// Implementation of Exynos specific power domain control which is used in
+// conjunction with runtime-pm. Support for both device-tree and non-device-tree
+// based power domain support is included.
+
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/pm_domain.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/pm_runtime.h>
+
+struct exynos_pm_domain_config {
+       /* Value for LOCAL_PWR_CFG and STATUS fields for each domain */
+       u32 local_pwr_cfg;
+};
+
+/*
+ * Exynos specific wrapper around the generic power domain
+ */
+struct exynos_pm_domain {
+       void __iomem *base;
+       struct generic_pm_domain pd;
+       u32 local_pwr_cfg;
+};
+
+static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
+{
+       struct exynos_pm_domain *pd;
+       void __iomem *base;
+       u32 timeout, pwr;
+       char *op;
+
+       pd = container_of(domain, struct exynos_pm_domain, pd);
+       base = pd->base;
+
+       pwr = power_on ? pd->local_pwr_cfg : 0;
+       writel_relaxed(pwr, base);
+
+       /* Wait max 1ms */
+       timeout = 10;
+
+       while ((readl_relaxed(base + 0x4) & pd->local_pwr_cfg) != pwr) {
+               if (!timeout) {
+                       op = (power_on) ? "enable" : "disable";
+                       pr_err("Power domain %s %s failed\n", domain->name, op);
+                       return -ETIMEDOUT;
+               }
+               timeout--;
+               cpu_relax();
+               usleep_range(80, 100);
+       }
+
+       return 0;
+}
+
+static int exynos_pd_power_on(struct generic_pm_domain *domain)
+{
+       return exynos_pd_power(domain, true);
+}
+
+static int exynos_pd_power_off(struct generic_pm_domain *domain)
+{
+       return exynos_pd_power(domain, false);
+}
+
+static const struct exynos_pm_domain_config exynos4210_cfg = {
+       .local_pwr_cfg          = 0x7,
+};
+
+static const struct exynos_pm_domain_config exynos5433_cfg = {
+       .local_pwr_cfg          = 0xf,
+};
+
+static const struct of_device_id exynos_pm_domain_of_match[] = {
+       {
+               .compatible = "samsung,exynos4210-pd",
+               .data = &exynos4210_cfg,
+       }, {
+               .compatible = "samsung,exynos5433-pd",
+               .data = &exynos5433_cfg,
+       },
+       { },
+};
+
+static const char *exynos_get_domain_name(struct device_node *node)
+{
+       const char *name;
+
+       if (of_property_read_string(node, "label", &name) < 0)
+               name = kbasename(node->full_name);
+       return kstrdup_const(name, GFP_KERNEL);
+}
+
+static int exynos_pd_probe(struct platform_device *pdev)
+{
+       const struct exynos_pm_domain_config *pm_domain_cfg;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct of_phandle_args child, parent;
+       struct exynos_pm_domain *pd;
+       int on, ret;
+
+       pm_domain_cfg = of_device_get_match_data(dev);
+       pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+       if (!pd)
+               return -ENOMEM;
+
+       pd->pd.name = exynos_get_domain_name(np);
+       if (!pd->pd.name)
+               return -ENOMEM;
+
+       pd->base = of_iomap(np, 0);
+       if (!pd->base) {
+               kfree_const(pd->pd.name);
+               return -ENODEV;
+       }
+
+       pd->pd.power_off = exynos_pd_power_off;
+       pd->pd.power_on = exynos_pd_power_on;
+       pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg;
+
+       on = readl_relaxed(pd->base + 0x4) & pd->local_pwr_cfg;
+
+       pm_genpd_init(&pd->pd, NULL, !on);
+       ret = of_genpd_add_provider_simple(np, &pd->pd);
+
+       if (ret == 0 && of_parse_phandle_with_args(np, "power-domains",
+                                     "#power-domain-cells", 0, &parent) == 0) {
+               child.np = np;
+               child.args_count = 0;
+
+               if (of_genpd_add_subdomain(&parent, &child))
+                       pr_warn("%pOF failed to add subdomain: %pOF\n",
+                               parent.np, child.np);
+               else
+                       pr_info("%pOF has as child subdomain: %pOF.\n",
+                               parent.np, child.np);
+       }
+
+       pm_runtime_enable(dev);
+       return ret;
+}
+
+static struct platform_driver exynos_pd_driver = {
+       .probe  = exynos_pd_probe,
+       .driver = {
+               .name           = "exynos-pd",
+               .of_match_table = exynos_pm_domain_of_match,
+               .suppress_bind_attrs = true,
+       }
+};
+
+static __init int exynos4_pm_init_power_domain(void)
+{
+       return platform_driver_register(&exynos_pd_driver);
+}
+core_initcall(exynos4_pm_init_power_domain);
diff --git a/drivers/pmdomain/st/Makefile b/drivers/pmdomain/st/Makefile
new file mode 100644 (file)
index 0000000..8fa5f98
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_ARCH_U8500)               += ste-ux500-pm-domain.o
diff --git a/drivers/pmdomain/st/ste-ux500-pm-domain.c b/drivers/pmdomain/st/ste-ux500-pm-domain.c
new file mode 100644 (file)
index 0000000..3d4f111
--- /dev/null
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2014 Linaro Ltd.
+ *
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * Implements PM domains using the generic PM domain for ux500.
+ */
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/pm_domain.h>
+
+#include <dt-bindings/arm/ux500_pm_domains.h>
+
+static int pd_power_off(struct generic_pm_domain *domain)
+{
+       /*
+        * Handle the gating of the PM domain regulator here.
+        *
+        * Drivers/subsystems handling devices in the PM domain needs to perform
+        * register context save/restore from their respective runtime PM
+        * callbacks, to be able to enable PM domain gating/ungating.
+        */
+       return 0;
+}
+
+static int pd_power_on(struct generic_pm_domain *domain)
+{
+       /*
+        * Handle the ungating of the PM domain regulator here.
+        *
+        * Drivers/subsystems handling devices in the PM domain needs to perform
+        * register context save/restore from their respective runtime PM
+        * callbacks, to be able to enable PM domain gating/ungating.
+        */
+       return 0;
+}
+
+static struct generic_pm_domain ux500_pm_domain_vape = {
+       .name = "VAPE",
+       .power_off = pd_power_off,
+       .power_on = pd_power_on,
+};
+
+static struct generic_pm_domain *ux500_pm_domains[NR_DOMAINS] = {
+       [DOMAIN_VAPE] = &ux500_pm_domain_vape,
+};
+
+static const struct of_device_id ux500_pm_domain_matches[] = {
+       { .compatible = "stericsson,ux500-pm-domains", },
+       { },
+};
+
+static int ux500_pm_domains_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct genpd_onecell_data *genpd_data;
+       int i;
+
+       if (!np)
+               return -ENODEV;
+
+       genpd_data = kzalloc(sizeof(*genpd_data), GFP_KERNEL);
+       if (!genpd_data)
+               return -ENOMEM;
+
+       genpd_data->domains = ux500_pm_domains;
+       genpd_data->num_domains = ARRAY_SIZE(ux500_pm_domains);
+
+       for (i = 0; i < ARRAY_SIZE(ux500_pm_domains); ++i)
+               pm_genpd_init(ux500_pm_domains[i], NULL, false);
+
+       of_genpd_add_provider_onecell(np, genpd_data);
+       return 0;
+}
+
+static struct platform_driver ux500_pm_domains_driver = {
+       .probe  = ux500_pm_domains_probe,
+       .driver = {
+               .name = "ux500_pm_domains",
+               .of_match_table = ux500_pm_domain_matches,
+       },
+};
+
+static int __init ux500_pm_domains_init(void)
+{
+       return platform_driver_register(&ux500_pm_domains_driver);
+}
+arch_initcall(ux500_pm_domains_init);
diff --git a/drivers/pmdomain/starfive/Makefile b/drivers/pmdomain/starfive/Makefile
new file mode 100644 (file)
index 0000000..975bba2
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_JH71XX_PMU)               += jh71xx-pmu.o
diff --git a/drivers/pmdomain/starfive/jh71xx-pmu.c b/drivers/pmdomain/starfive/jh71xx-pmu.c
new file mode 100644 (file)
index 0000000..7d5f50d
--- /dev/null
@@ -0,0 +1,383 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * StarFive JH71XX PMU (Power Management Unit) Controller Driver
+ *
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <dt-bindings/power/starfive,jh7110-pmu.h>
+
+/* register offset */
+#define JH71XX_PMU_SW_TURN_ON_POWER    0x0C
+#define JH71XX_PMU_SW_TURN_OFF_POWER   0x10
+#define JH71XX_PMU_SW_ENCOURAGE                0x44
+#define JH71XX_PMU_TIMER_INT_MASK      0x48
+#define JH71XX_PMU_CURR_POWER_MODE     0x80
+#define JH71XX_PMU_EVENT_STATUS                0x88
+#define JH71XX_PMU_INT_STATUS          0x8C
+
+/* sw encourage cfg */
+#define JH71XX_PMU_SW_ENCOURAGE_EN_LO  0x05
+#define JH71XX_PMU_SW_ENCOURAGE_EN_HI  0x50
+#define JH71XX_PMU_SW_ENCOURAGE_DIS_LO 0x0A
+#define JH71XX_PMU_SW_ENCOURAGE_DIS_HI 0xA0
+#define JH71XX_PMU_SW_ENCOURAGE_ON     0xFF
+
+/* pmu int status */
+#define JH71XX_PMU_INT_SEQ_DONE                BIT(0)
+#define JH71XX_PMU_INT_HW_REQ          BIT(1)
+#define JH71XX_PMU_INT_SW_FAIL         GENMASK(3, 2)
+#define JH71XX_PMU_INT_HW_FAIL         GENMASK(5, 4)
+#define JH71XX_PMU_INT_PCH_FAIL                GENMASK(8, 6)
+#define JH71XX_PMU_INT_ALL_MASK                GENMASK(8, 0)
+
+/*
+ * The time required for switching power status is based on the time
+ * to turn on the largest domain's power, which is at microsecond level
+ */
+#define JH71XX_PMU_TIMEOUT_US          100
+
+struct jh71xx_domain_info {
+       const char * const name;
+       unsigned int flags;
+       u8 bit;
+};
+
+struct jh71xx_pmu_match_data {
+       const struct jh71xx_domain_info *domain_info;
+       int num_domains;
+};
+
+struct jh71xx_pmu {
+       struct device *dev;
+       const struct jh71xx_pmu_match_data *match_data;
+       void __iomem *base;
+       struct generic_pm_domain **genpd;
+       struct genpd_onecell_data genpd_data;
+       int irq;
+       spinlock_t lock;        /* protects pmu reg */
+};
+
+struct jh71xx_pmu_dev {
+       const struct jh71xx_domain_info *domain_info;
+       struct jh71xx_pmu *pmu;
+       struct generic_pm_domain genpd;
+};
+
+static int jh71xx_pmu_get_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool *is_on)
+{
+       struct jh71xx_pmu *pmu = pmd->pmu;
+
+       if (!mask)
+               return -EINVAL;
+
+       *is_on = readl(pmu->base + JH71XX_PMU_CURR_POWER_MODE) & mask;
+
+       return 0;
+}
+
+static int jh71xx_pmu_set_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool on)
+{
+       struct jh71xx_pmu *pmu = pmd->pmu;
+       unsigned long flags;
+       u32 val;
+       u32 mode;
+       u32 encourage_lo;
+       u32 encourage_hi;
+       bool is_on;
+       int ret;
+
+       ret = jh71xx_pmu_get_state(pmd, mask, &is_on);
+       if (ret) {
+               dev_dbg(pmu->dev, "unable to get current state for %s\n",
+                       pmd->genpd.name);
+               return ret;
+       }
+
+       if (is_on == on) {
+               dev_dbg(pmu->dev, "pm domain [%s] is already %sable status.\n",
+                       pmd->genpd.name, on ? "en" : "dis");
+               return 0;
+       }
+
+       spin_lock_irqsave(&pmu->lock, flags);
+
+       /*
+        * The PMU accepts software encourage to switch power mode in the following 2 steps:
+        *
+        * 1.Configure the register SW_TURN_ON_POWER (offset 0x0c) by writing 1 to
+        *   the bit corresponding to the power domain that will be turned on
+        *   and writing 0 to the others.
+        *   Likewise, configure the register SW_TURN_OFF_POWER (offset 0x10) by
+        *   writing 1 to the bit corresponding to the power domain that will be
+        *   turned off and writing 0 to the others.
+        */
+       if (on) {
+               mode = JH71XX_PMU_SW_TURN_ON_POWER;
+               encourage_lo = JH71XX_PMU_SW_ENCOURAGE_EN_LO;
+               encourage_hi = JH71XX_PMU_SW_ENCOURAGE_EN_HI;
+       } else {
+               mode = JH71XX_PMU_SW_TURN_OFF_POWER;
+               encourage_lo = JH71XX_PMU_SW_ENCOURAGE_DIS_LO;
+               encourage_hi = JH71XX_PMU_SW_ENCOURAGE_DIS_HI;
+       }
+
+       writel(mask, pmu->base + mode);
+
+       /*
+        * 2.Write SW encourage command sequence to the Software Encourage Reg (offset 0x44)
+        *   First write SW_MODE_ENCOURAGE_ON to JH71XX_PMU_SW_ENCOURAGE. This will reset
+        *   the state machine which parses the command sequence. This register must be
+        *   written every time software wants to power on/off a domain.
+        *   Then write the lower bits of the command sequence, followed by the upper
+        *   bits. The sequence differs between powering on & off a domain.
+        */
+       writel(JH71XX_PMU_SW_ENCOURAGE_ON, pmu->base + JH71XX_PMU_SW_ENCOURAGE);
+       writel(encourage_lo, pmu->base + JH71XX_PMU_SW_ENCOURAGE);
+       writel(encourage_hi, pmu->base + JH71XX_PMU_SW_ENCOURAGE);
+
+       spin_unlock_irqrestore(&pmu->lock, flags);
+
+       /* Wait for the power domain bit to be enabled / disabled */
+       if (on) {
+               ret = readl_poll_timeout_atomic(pmu->base + JH71XX_PMU_CURR_POWER_MODE,
+                                               val, val & mask,
+                                               1, JH71XX_PMU_TIMEOUT_US);
+       } else {
+               ret = readl_poll_timeout_atomic(pmu->base + JH71XX_PMU_CURR_POWER_MODE,
+                                               val, !(val & mask),
+                                               1, JH71XX_PMU_TIMEOUT_US);
+       }
+
+       if (ret) {
+               dev_err(pmu->dev, "%s: failed to power %s\n",
+                       pmd->genpd.name, on ? "on" : "off");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int jh71xx_pmu_on(struct generic_pm_domain *genpd)
+{
+       struct jh71xx_pmu_dev *pmd = container_of(genpd,
+                                                 struct jh71xx_pmu_dev, genpd);
+       u32 pwr_mask = BIT(pmd->domain_info->bit);
+
+       return jh71xx_pmu_set_state(pmd, pwr_mask, true);
+}
+
+static int jh71xx_pmu_off(struct generic_pm_domain *genpd)
+{
+       struct jh71xx_pmu_dev *pmd = container_of(genpd,
+                                                 struct jh71xx_pmu_dev, genpd);
+       u32 pwr_mask = BIT(pmd->domain_info->bit);
+
+       return jh71xx_pmu_set_state(pmd, pwr_mask, false);
+}
+
+static void jh71xx_pmu_int_enable(struct jh71xx_pmu *pmu, u32 mask, bool enable)
+{
+       u32 val;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pmu->lock, flags);
+       val = readl(pmu->base + JH71XX_PMU_TIMER_INT_MASK);
+
+       if (enable)
+               val &= ~mask;
+       else
+               val |= mask;
+
+       writel(val, pmu->base + JH71XX_PMU_TIMER_INT_MASK);
+       spin_unlock_irqrestore(&pmu->lock, flags);
+}
+
+static irqreturn_t jh71xx_pmu_interrupt(int irq, void *data)
+{
+       struct jh71xx_pmu *pmu = data;
+       u32 val;
+
+       val = readl(pmu->base + JH71XX_PMU_INT_STATUS);
+
+       if (val & JH71XX_PMU_INT_SEQ_DONE)
+               dev_dbg(pmu->dev, "sequence done.\n");
+       if (val & JH71XX_PMU_INT_HW_REQ)
+               dev_dbg(pmu->dev, "hardware encourage requestion.\n");
+       if (val & JH71XX_PMU_INT_SW_FAIL)
+               dev_err(pmu->dev, "software encourage fail.\n");
+       if (val & JH71XX_PMU_INT_HW_FAIL)
+               dev_err(pmu->dev, "hardware encourage fail.\n");
+       if (val & JH71XX_PMU_INT_PCH_FAIL)
+               dev_err(pmu->dev, "p-channel fail event.\n");
+
+       /* clear interrupts */
+       writel(val, pmu->base + JH71XX_PMU_INT_STATUS);
+       writel(val, pmu->base + JH71XX_PMU_EVENT_STATUS);
+
+       return IRQ_HANDLED;
+}
+
+static int jh71xx_pmu_init_domain(struct jh71xx_pmu *pmu, int index)
+{
+       struct jh71xx_pmu_dev *pmd;
+       u32 pwr_mask;
+       int ret;
+       bool is_on = false;
+
+       pmd = devm_kzalloc(pmu->dev, sizeof(*pmd), GFP_KERNEL);
+       if (!pmd)
+               return -ENOMEM;
+
+       pmd->domain_info = &pmu->match_data->domain_info[index];
+       pmd->pmu = pmu;
+       pwr_mask = BIT(pmd->domain_info->bit);
+
+       pmd->genpd.name = pmd->domain_info->name;
+       pmd->genpd.flags = pmd->domain_info->flags;
+
+       ret = jh71xx_pmu_get_state(pmd, pwr_mask, &is_on);
+       if (ret)
+               dev_warn(pmu->dev, "unable to get current state for %s\n",
+                        pmd->genpd.name);
+
+       pmd->genpd.power_on = jh71xx_pmu_on;
+       pmd->genpd.power_off = jh71xx_pmu_off;
+       pm_genpd_init(&pmd->genpd, NULL, !is_on);
+
+       pmu->genpd_data.domains[index] = &pmd->genpd;
+
+       return 0;
+}
+
+static int jh71xx_pmu_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       const struct jh71xx_pmu_match_data *match_data;
+       struct jh71xx_pmu *pmu;
+       unsigned int i;
+       int ret;
+
+       pmu = devm_kzalloc(dev, sizeof(*pmu), GFP_KERNEL);
+       if (!pmu)
+               return -ENOMEM;
+
+       pmu->base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(pmu->base))
+               return PTR_ERR(pmu->base);
+
+       pmu->irq = platform_get_irq(pdev, 0);
+       if (pmu->irq < 0)
+               return pmu->irq;
+
+       ret = devm_request_irq(dev, pmu->irq, jh71xx_pmu_interrupt,
+                              0, pdev->name, pmu);
+       if (ret)
+               dev_err(dev, "failed to request irq\n");
+
+       match_data = of_device_get_match_data(dev);
+       if (!match_data)
+               return -EINVAL;
+
+       pmu->genpd = devm_kcalloc(dev, match_data->num_domains,
+                                 sizeof(struct generic_pm_domain *),
+                                 GFP_KERNEL);
+       if (!pmu->genpd)
+               return -ENOMEM;
+
+       pmu->dev = dev;
+       pmu->match_data = match_data;
+       pmu->genpd_data.domains = pmu->genpd;
+       pmu->genpd_data.num_domains = match_data->num_domains;
+
+       for (i = 0; i < match_data->num_domains; i++) {
+               ret = jh71xx_pmu_init_domain(pmu, i);
+               if (ret) {
+                       dev_err(dev, "failed to initialize power domain\n");
+                       return ret;
+               }
+       }
+
+       spin_lock_init(&pmu->lock);
+       jh71xx_pmu_int_enable(pmu, JH71XX_PMU_INT_ALL_MASK & ~JH71XX_PMU_INT_PCH_FAIL, true);
+
+       ret = of_genpd_add_provider_onecell(np, &pmu->genpd_data);
+       if (ret) {
+               dev_err(dev, "failed to register genpd driver: %d\n", ret);
+               return ret;
+       }
+
+       dev_dbg(dev, "registered %u power domains\n", i);
+
+       return 0;
+}
+
+static const struct jh71xx_domain_info jh7110_power_domains[] = {
+       [JH7110_PD_SYSTOP] = {
+               .name = "SYSTOP",
+               .bit = 0,
+               .flags = GENPD_FLAG_ALWAYS_ON,
+       },
+       [JH7110_PD_CPU] = {
+               .name = "CPU",
+               .bit = 1,
+               .flags = GENPD_FLAG_ALWAYS_ON,
+       },
+       [JH7110_PD_GPUA] = {
+               .name = "GPUA",
+               .bit = 2,
+       },
+       [JH7110_PD_VDEC] = {
+               .name = "VDEC",
+               .bit = 3,
+       },
+       [JH7110_PD_VOUT] = {
+               .name = "VOUT",
+               .bit = 4,
+       },
+       [JH7110_PD_ISP] = {
+               .name = "ISP",
+               .bit = 5,
+       },
+       [JH7110_PD_VENC] = {
+               .name = "VENC",
+               .bit = 6,
+       },
+};
+
+static const struct jh71xx_pmu_match_data jh7110_pmu = {
+       .num_domains = ARRAY_SIZE(jh7110_power_domains),
+       .domain_info = jh7110_power_domains,
+};
+
+static const struct of_device_id jh71xx_pmu_of_match[] = {
+       {
+               .compatible = "starfive,jh7110-pmu",
+               .data = (void *)&jh7110_pmu,
+       }, {
+               /* sentinel */
+       }
+};
+
+static struct platform_driver jh71xx_pmu_driver = {
+       .probe = jh71xx_pmu_probe,
+       .driver = {
+               .name = "jh71xx-pmu",
+               .of_match_table = jh71xx_pmu_of_match,
+               .suppress_bind_attrs = true,
+       },
+};
+builtin_platform_driver(jh71xx_pmu_driver);
+
+MODULE_AUTHOR("Walker Chen <walker.chen@starfivetech.com>");
+MODULE_DESCRIPTION("StarFive JH71XX PMU Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pmdomain/sunxi/Makefile b/drivers/pmdomain/sunxi/Makefile
new file mode 100644 (file)
index 0000000..ec1d7a2
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_SUN20I_PPU)               += sun20i-ppu.o
diff --git a/drivers/pmdomain/sunxi/sun20i-ppu.c b/drivers/pmdomain/sunxi/sun20i-ppu.c
new file mode 100644 (file)
index 0000000..8700f9d
--- /dev/null
@@ -0,0 +1,207 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/reset.h>
+
+#define PD_STATE_ON                    1
+#define PD_STATE_OFF                   2
+
+#define PD_RSTN_REG                    0x00
+#define PD_CLK_GATE_REG                        0x04
+#define PD_PWROFF_GATE_REG             0x08
+#define PD_PSW_ON_REG                  0x0c
+#define PD_PSW_OFF_REG                 0x10
+#define PD_PSW_DELAY_REG               0x14
+#define PD_OFF_DELAY_REG               0x18
+#define PD_ON_DELAY_REG                        0x1c
+#define PD_COMMAND_REG                 0x20
+#define PD_STATUS_REG                  0x24
+#define PD_STATUS_COMPLETE                     BIT(1)
+#define PD_STATUS_BUSY                         BIT(3)
+#define PD_STATUS_STATE                                GENMASK(17, 16)
+#define PD_ACTIVE_CTRL_REG             0x2c
+#define PD_GATE_STATUS_REG             0x30
+#define PD_RSTN_STATUS                         BIT(0)
+#define PD_CLK_GATE_STATUS                     BIT(1)
+#define PD_PWROFF_GATE_STATUS                  BIT(2)
+#define PD_PSW_STATUS_REG              0x34
+
+#define PD_REGS_SIZE                   0x80
+
+struct sun20i_ppu_desc {
+       const char *const               *names;
+       unsigned int                    num_domains;
+};
+
+struct sun20i_ppu_pd {
+       struct generic_pm_domain        genpd;
+       void __iomem                    *base;
+};
+
+#define to_sun20i_ppu_pd(_genpd) \
+       container_of(_genpd, struct sun20i_ppu_pd, genpd)
+
+static bool sun20i_ppu_pd_is_on(const struct sun20i_ppu_pd *pd)
+{
+       u32 status = readl(pd->base + PD_STATUS_REG);
+
+       return FIELD_GET(PD_STATUS_STATE, status) == PD_STATE_ON;
+}
+
+static int sun20i_ppu_pd_set_power(const struct sun20i_ppu_pd *pd, bool power_on)
+{
+       u32 state, status;
+       int ret;
+
+       if (sun20i_ppu_pd_is_on(pd) == power_on)
+               return 0;
+
+       /* Wait for the power controller to be idle. */
+       ret = readl_poll_timeout(pd->base + PD_STATUS_REG, status,
+                                !(status & PD_STATUS_BUSY), 100, 1000);
+       if (ret)
+               return ret;
+
+       state = power_on ? PD_STATE_ON : PD_STATE_OFF;
+       writel(state, pd->base + PD_COMMAND_REG);
+
+       /* Wait for the state transition to complete. */
+       ret = readl_poll_timeout(pd->base + PD_STATUS_REG, status,
+                                FIELD_GET(PD_STATUS_STATE, status) == state &&
+                                (status & PD_STATUS_COMPLETE), 100, 1000);
+       if (ret)
+               return ret;
+
+       /* Clear the completion flag. */
+       writel(status, pd->base + PD_STATUS_REG);
+
+       return 0;
+}
+
+static int sun20i_ppu_pd_power_on(struct generic_pm_domain *genpd)
+{
+       const struct sun20i_ppu_pd *pd = to_sun20i_ppu_pd(genpd);
+
+       return sun20i_ppu_pd_set_power(pd, true);
+}
+
+static int sun20i_ppu_pd_power_off(struct generic_pm_domain *genpd)
+{
+       const struct sun20i_ppu_pd *pd = to_sun20i_ppu_pd(genpd);
+
+       return sun20i_ppu_pd_set_power(pd, false);
+}
+
+static int sun20i_ppu_probe(struct platform_device *pdev)
+{
+       const struct sun20i_ppu_desc *desc;
+       struct device *dev = &pdev->dev;
+       struct genpd_onecell_data *ppu;
+       struct sun20i_ppu_pd *pds;
+       struct reset_control *rst;
+       void __iomem *base;
+       struct clk *clk;
+       int ret;
+
+       desc = of_device_get_match_data(dev);
+       if (!desc)
+               return -EINVAL;
+
+       pds = devm_kcalloc(dev, desc->num_domains, sizeof(*pds), GFP_KERNEL);
+       if (!pds)
+               return -ENOMEM;
+
+       ppu = devm_kzalloc(dev, sizeof(*ppu), GFP_KERNEL);
+       if (!ppu)
+               return -ENOMEM;
+
+       ppu->domains = devm_kcalloc(dev, desc->num_domains,
+                                   sizeof(*ppu->domains), GFP_KERNEL);
+       if (!ppu->domains)
+               return -ENOMEM;
+
+       ppu->num_domains = desc->num_domains;
+       platform_set_drvdata(pdev, ppu);
+
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       clk = devm_clk_get_enabled(dev, NULL);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       rst = devm_reset_control_get_exclusive(dev, NULL);
+       if (IS_ERR(rst))
+               return PTR_ERR(rst);
+
+       ret = reset_control_deassert(rst);
+       if (ret)
+               return ret;
+
+       for (unsigned int i = 0; i < ppu->num_domains; ++i) {
+               struct sun20i_ppu_pd *pd = &pds[i];
+
+               pd->genpd.name          = desc->names[i];
+               pd->genpd.power_off     = sun20i_ppu_pd_power_off;
+               pd->genpd.power_on      = sun20i_ppu_pd_power_on;
+               pd->base                = base + PD_REGS_SIZE * i;
+
+               ret = pm_genpd_init(&pd->genpd, NULL, sun20i_ppu_pd_is_on(pd));
+               if (ret) {
+                       dev_warn(dev, "Failed to add '%s' domain: %d\n",
+                                pd->genpd.name, ret);
+                       continue;
+               }
+
+               ppu->domains[i] = &pd->genpd;
+       }
+
+       ret = of_genpd_add_provider_onecell(dev->of_node, ppu);
+       if (ret)
+               dev_warn(dev, "Failed to add provider: %d\n", ret);
+
+       return 0;
+}
+
+static const char *const sun20i_d1_ppu_pd_names[] = {
+       "CPU",
+       "VE",
+       "DSP",
+};
+
+static const struct sun20i_ppu_desc sun20i_d1_ppu_desc = {
+       .names          = sun20i_d1_ppu_pd_names,
+       .num_domains    = ARRAY_SIZE(sun20i_d1_ppu_pd_names),
+};
+
+static const struct of_device_id sun20i_ppu_of_match[] = {
+       {
+               .compatible     = "allwinner,sun20i-d1-ppu",
+               .data           = &sun20i_d1_ppu_desc,
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(of, sun20i_ppu_of_match);
+
+static struct platform_driver sun20i_ppu_driver = {
+       .probe  = sun20i_ppu_probe,
+       .driver = {
+               .name                   = "sun20i-ppu",
+               .of_match_table         = sun20i_ppu_of_match,
+               /* Power domains cannot be removed while they are in use. */
+               .suppress_bind_attrs    = true,
+       },
+};
+module_platform_driver(sun20i_ppu_driver);
+
+MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
+MODULE_DESCRIPTION("Allwinner D1 PPU power domain driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pmdomain/tegra/Makefile b/drivers/pmdomain/tegra/Makefile
new file mode 100644 (file)
index 0000000..ec8acfd
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_SOC_TEGRA_POWERGATE_BPMP) += powergate-bpmp.o
diff --git a/drivers/pmdomain/tegra/powergate-bpmp.c b/drivers/pmdomain/tegra/powergate-bpmp.c
new file mode 100644 (file)
index 0000000..179ed89
--- /dev/null
@@ -0,0 +1,361 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved
+ */
+
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+
+#include <soc/tegra/bpmp.h>
+#include <soc/tegra/bpmp-abi.h>
+
+struct tegra_powergate_info {
+       unsigned int id;
+       char *name;
+};
+
+struct tegra_powergate {
+       struct generic_pm_domain genpd;
+       struct tegra_bpmp *bpmp;
+       unsigned int id;
+};
+
+static inline struct tegra_powergate *
+to_tegra_powergate(struct generic_pm_domain *genpd)
+{
+       return container_of(genpd, struct tegra_powergate, genpd);
+}
+
+static int tegra_bpmp_powergate_set_state(struct tegra_bpmp *bpmp,
+                                         unsigned int id, u32 state)
+{
+       struct mrq_pg_request request;
+       struct tegra_bpmp_message msg;
+       int err;
+
+       memset(&request, 0, sizeof(request));
+       request.cmd = CMD_PG_SET_STATE;
+       request.id = id;
+       request.set_state.state = state;
+
+       memset(&msg, 0, sizeof(msg));
+       msg.mrq = MRQ_PG;
+       msg.tx.data = &request;
+       msg.tx.size = sizeof(request);
+
+       err = tegra_bpmp_transfer(bpmp, &msg);
+       if (err < 0)
+               return err;
+       else if (msg.rx.ret < 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int tegra_bpmp_powergate_get_state(struct tegra_bpmp *bpmp,
+                                         unsigned int id)
+{
+       struct mrq_pg_response response;
+       struct mrq_pg_request request;
+       struct tegra_bpmp_message msg;
+       int err;
+
+       memset(&request, 0, sizeof(request));
+       request.cmd = CMD_PG_GET_STATE;
+       request.id = id;
+
+       memset(&response, 0, sizeof(response));
+
+       memset(&msg, 0, sizeof(msg));
+       msg.mrq = MRQ_PG;
+       msg.tx.data = &request;
+       msg.tx.size = sizeof(request);
+       msg.rx.data = &response;
+       msg.rx.size = sizeof(response);
+
+       err = tegra_bpmp_transfer(bpmp, &msg);
+       if (err < 0)
+               return PG_STATE_OFF;
+       else if (msg.rx.ret < 0)
+               return -EINVAL;
+
+       return response.get_state.state;
+}
+
+static int tegra_bpmp_powergate_get_max_id(struct tegra_bpmp *bpmp)
+{
+       struct mrq_pg_response response;
+       struct mrq_pg_request request;
+       struct tegra_bpmp_message msg;
+       int err;
+
+       memset(&request, 0, sizeof(request));
+       request.cmd = CMD_PG_GET_MAX_ID;
+
+       memset(&response, 0, sizeof(response));
+
+       memset(&msg, 0, sizeof(msg));
+       msg.mrq = MRQ_PG;
+       msg.tx.data = &request;
+       msg.tx.size = sizeof(request);
+       msg.rx.data = &response;
+       msg.rx.size = sizeof(response);
+
+       err = tegra_bpmp_transfer(bpmp, &msg);
+       if (err < 0)
+               return err;
+       else if (msg.rx.ret < 0)
+               return -EINVAL;
+
+       return response.get_max_id.max_id;
+}
+
+static char *tegra_bpmp_powergate_get_name(struct tegra_bpmp *bpmp,
+                                          unsigned int id)
+{
+       struct mrq_pg_response response;
+       struct mrq_pg_request request;
+       struct tegra_bpmp_message msg;
+       int err;
+
+       memset(&request, 0, sizeof(request));
+       request.cmd = CMD_PG_GET_NAME;
+       request.id = id;
+
+       memset(&response, 0, sizeof(response));
+
+       memset(&msg, 0, sizeof(msg));
+       msg.mrq = MRQ_PG;
+       msg.tx.data = &request;
+       msg.tx.size = sizeof(request);
+       msg.rx.data = &response;
+       msg.rx.size = sizeof(response);
+
+       err = tegra_bpmp_transfer(bpmp, &msg);
+       if (err < 0 || msg.rx.ret < 0)
+               return NULL;
+
+       return kstrdup(response.get_name.name, GFP_KERNEL);
+}
+
+static inline bool tegra_bpmp_powergate_is_powered(struct tegra_bpmp *bpmp,
+                                                  unsigned int id)
+{
+       return tegra_bpmp_powergate_get_state(bpmp, id) != PG_STATE_OFF;
+}
+
+static int tegra_powergate_power_on(struct generic_pm_domain *domain)
+{
+       struct tegra_powergate *powergate = to_tegra_powergate(domain);
+       struct tegra_bpmp *bpmp = powergate->bpmp;
+
+       return tegra_bpmp_powergate_set_state(bpmp, powergate->id,
+                                             PG_STATE_ON);
+}
+
+static int tegra_powergate_power_off(struct generic_pm_domain *domain)
+{
+       struct tegra_powergate *powergate = to_tegra_powergate(domain);
+       struct tegra_bpmp *bpmp = powergate->bpmp;
+
+       return tegra_bpmp_powergate_set_state(bpmp, powergate->id,
+                                             PG_STATE_OFF);
+}
+
+static struct tegra_powergate *
+tegra_powergate_add(struct tegra_bpmp *bpmp,
+                   const struct tegra_powergate_info *info)
+{
+       struct tegra_powergate *powergate;
+       bool off;
+       int err;
+
+       off = !tegra_bpmp_powergate_is_powered(bpmp, info->id);
+
+       powergate = devm_kzalloc(bpmp->dev, sizeof(*powergate), GFP_KERNEL);
+       if (!powergate)
+               return ERR_PTR(-ENOMEM);
+
+       powergate->id = info->id;
+       powergate->bpmp = bpmp;
+
+       powergate->genpd.name = kstrdup(info->name, GFP_KERNEL);
+       powergate->genpd.power_on = tegra_powergate_power_on;
+       powergate->genpd.power_off = tegra_powergate_power_off;
+
+       err = pm_genpd_init(&powergate->genpd, NULL, off);
+       if (err < 0) {
+               kfree(powergate->genpd.name);
+               return ERR_PTR(err);
+       }
+
+       return powergate;
+}
+
+static void tegra_powergate_remove(struct tegra_powergate *powergate)
+{
+       struct generic_pm_domain *genpd = &powergate->genpd;
+       struct tegra_bpmp *bpmp = powergate->bpmp;
+       int err;
+
+       err = pm_genpd_remove(genpd);
+       if (err < 0)
+               dev_err(bpmp->dev, "failed to remove power domain %s: %d\n",
+                       genpd->name, err);
+
+       kfree(genpd->name);
+}
+
+static int
+tegra_bpmp_probe_powergates(struct tegra_bpmp *bpmp,
+                           struct tegra_powergate_info **powergatesp)
+{
+       struct tegra_powergate_info *powergates;
+       unsigned int max_id, id, count = 0;
+       unsigned int num_holes = 0;
+       int err;
+
+       err = tegra_bpmp_powergate_get_max_id(bpmp);
+       if (err < 0)
+               return err;
+
+       max_id = err;
+
+       dev_dbg(bpmp->dev, "maximum powergate ID: %u\n", max_id);
+
+       powergates = kcalloc(max_id + 1, sizeof(*powergates), GFP_KERNEL);
+       if (!powergates)
+               return -ENOMEM;
+
+       for (id = 0; id <= max_id; id++) {
+               struct tegra_powergate_info *info = &powergates[count];
+
+               info->name = tegra_bpmp_powergate_get_name(bpmp, id);
+               if (!info->name || info->name[0] == '\0') {
+                       num_holes++;
+                       continue;
+               }
+
+               info->id = id;
+               count++;
+       }
+
+       dev_dbg(bpmp->dev, "holes: %u\n", num_holes);
+
+       *powergatesp = powergates;
+
+       return count;
+}
+
+static int tegra_bpmp_add_powergates(struct tegra_bpmp *bpmp,
+                                    struct tegra_powergate_info *powergates,
+                                    unsigned int count)
+{
+       struct genpd_onecell_data *genpd = &bpmp->genpd;
+       struct generic_pm_domain **domains;
+       struct tegra_powergate *powergate;
+       unsigned int i;
+       int err;
+
+       domains = kcalloc(count, sizeof(*domains), GFP_KERNEL);
+       if (!domains)
+               return -ENOMEM;
+
+       for (i = 0; i < count; i++) {
+               powergate = tegra_powergate_add(bpmp, &powergates[i]);
+               if (IS_ERR(powergate)) {
+                       err = PTR_ERR(powergate);
+                       goto remove;
+               }
+
+               dev_dbg(bpmp->dev, "added power domain %s\n",
+                       powergate->genpd.name);
+               domains[i] = &powergate->genpd;
+       }
+
+       genpd->num_domains = count;
+       genpd->domains = domains;
+
+       return 0;
+
+remove:
+       while (i--) {
+               powergate = to_tegra_powergate(domains[i]);
+               tegra_powergate_remove(powergate);
+       }
+
+       kfree(domains);
+       return err;
+}
+
+static void tegra_bpmp_remove_powergates(struct tegra_bpmp *bpmp)
+{
+       struct genpd_onecell_data *genpd = &bpmp->genpd;
+       unsigned int i = genpd->num_domains;
+       struct tegra_powergate *powergate;
+
+       while (i--) {
+               dev_dbg(bpmp->dev, "removing power domain %s\n",
+                       genpd->domains[i]->name);
+               powergate = to_tegra_powergate(genpd->domains[i]);
+               tegra_powergate_remove(powergate);
+       }
+}
+
+static struct generic_pm_domain *
+tegra_powergate_xlate(struct of_phandle_args *spec, void *data)
+{
+       struct generic_pm_domain *domain = ERR_PTR(-ENOENT);
+       struct genpd_onecell_data *genpd = data;
+       unsigned int i;
+
+       for (i = 0; i < genpd->num_domains; i++) {
+               struct tegra_powergate *powergate;
+
+               powergate = to_tegra_powergate(genpd->domains[i]);
+               if (powergate->id == spec->args[0]) {
+                       domain = &powergate->genpd;
+                       break;
+               }
+       }
+
+       return domain;
+}
+
+int tegra_bpmp_init_powergates(struct tegra_bpmp *bpmp)
+{
+       struct device_node *np = bpmp->dev->of_node;
+       struct tegra_powergate_info *powergates;
+       struct device *dev = bpmp->dev;
+       unsigned int count, i;
+       int err;
+
+       err = tegra_bpmp_probe_powergates(bpmp, &powergates);
+       if (err < 0)
+               return err;
+
+       count = err;
+
+       dev_dbg(dev, "%u power domains probed\n", count);
+
+       err = tegra_bpmp_add_powergates(bpmp, powergates, count);
+       if (err < 0)
+               goto free;
+
+       bpmp->genpd.xlate = tegra_powergate_xlate;
+
+       err = of_genpd_add_provider_onecell(np, &bpmp->genpd);
+       if (err < 0) {
+               dev_err(dev, "failed to add power domain provider: %d\n", err);
+               tegra_bpmp_remove_powergates(bpmp);
+       }
+
+free:
+       for (i = 0; i < count; i++)
+               kfree(powergates[i].name);
+
+       kfree(powergates);
+       return err;
+}
diff --git a/drivers/pmdomain/ti/Makefile b/drivers/pmdomain/ti/Makefile
new file mode 100644 (file)
index 0000000..69580af
--- /dev/null
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_ARCH_OMAP2PLUS)           += omap_prm.o
+obj-$(CONFIG_TI_SCI_PM_DOMAINS)                += ti_sci_pm_domains.o
diff --git a/drivers/pmdomain/ti/omap_prm.c b/drivers/pmdomain/ti/omap_prm.c
new file mode 100644 (file)
index 0000000..c2feae3
--- /dev/null
@@ -0,0 +1,989 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * OMAP2+ PRM driver
+ *
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ *     Tero Kristo <t-kristo@ti.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_domain.h>
+#include <linux/reset-controller.h>
+#include <linux/delay.h>
+
+#include <linux/platform_data/ti-prm.h>
+
+enum omap_prm_domain_mode {
+       OMAP_PRMD_OFF,
+       OMAP_PRMD_RETENTION,
+       OMAP_PRMD_ON_INACTIVE,
+       OMAP_PRMD_ON_ACTIVE,
+};
+
+struct omap_prm_domain_map {
+       unsigned int usable_modes;      /* Mask of hardware supported modes */
+       unsigned long statechange:1;    /* Optional low-power state change */
+       unsigned long logicretstate:1;  /* Optional logic off mode */
+};
+
+struct omap_prm_domain {
+       struct device *dev;
+       struct omap_prm *prm;
+       struct generic_pm_domain pd;
+       u16 pwrstctrl;
+       u16 pwrstst;
+       const struct omap_prm_domain_map *cap;
+       u32 pwrstctrl_saved;
+       unsigned int uses_pm_clk:1;
+};
+
+struct omap_rst_map {
+       s8 rst;
+       s8 st;
+};
+
+struct omap_prm_data {
+       u32 base;
+       const char *name;
+       const char *clkdm_name;
+       u16 pwrstctrl;
+       u16 pwrstst;
+       const struct omap_prm_domain_map *dmap;
+       u16 rstctrl;
+       u16 rstst;
+       const struct omap_rst_map *rstmap;
+       u8 flags;
+};
+
+struct omap_prm {
+       const struct omap_prm_data *data;
+       void __iomem *base;
+       struct omap_prm_domain *prmd;
+};
+
+struct omap_reset_data {
+       struct reset_controller_dev rcdev;
+       struct omap_prm *prm;
+       u32 mask;
+       spinlock_t lock;
+       struct clockdomain *clkdm;
+       struct device *dev;
+};
+
+#define genpd_to_prm_domain(gpd) container_of(gpd, struct omap_prm_domain, pd)
+#define to_omap_reset_data(p) container_of((p), struct omap_reset_data, rcdev)
+
+#define OMAP_MAX_RESETS                8
+#define OMAP_RESET_MAX_WAIT    10000
+
+#define OMAP_PRM_HAS_RSTCTRL   BIT(0)
+#define OMAP_PRM_HAS_RSTST     BIT(1)
+#define OMAP_PRM_HAS_NO_CLKDM  BIT(2)
+#define OMAP_PRM_RET_WHEN_IDLE BIT(3)
+
+#define OMAP_PRM_HAS_RESETS    (OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_RSTST)
+
+#define PRM_STATE_MAX_WAIT     10000
+#define PRM_LOGICRETSTATE      BIT(2)
+#define PRM_LOWPOWERSTATECHANGE        BIT(4)
+#define PRM_POWERSTATE_MASK    OMAP_PRMD_ON_ACTIVE
+
+#define PRM_ST_INTRANSITION    BIT(20)
+
+static const struct omap_prm_domain_map omap_prm_all = {
+       .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_ON_INACTIVE) |
+                       BIT(OMAP_PRMD_RETENTION) | BIT(OMAP_PRMD_OFF),
+       .statechange = 1,
+       .logicretstate = 1,
+};
+
+static const struct omap_prm_domain_map omap_prm_noinact = {
+       .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_RETENTION) |
+                       BIT(OMAP_PRMD_OFF),
+       .statechange = 1,
+       .logicretstate = 1,
+};
+
+static const struct omap_prm_domain_map omap_prm_nooff = {
+       .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_ON_INACTIVE) |
+                       BIT(OMAP_PRMD_RETENTION),
+       .statechange = 1,
+       .logicretstate = 1,
+};
+
+static const struct omap_prm_domain_map omap_prm_onoff_noauto = {
+       .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_OFF),
+       .statechange = 1,
+};
+
+static const struct omap_prm_domain_map omap_prm_alwon = {
+       .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE),
+};
+
+static const struct omap_prm_domain_map omap_prm_reton = {
+       .usable_modes = BIT(OMAP_PRMD_ON_ACTIVE) | BIT(OMAP_PRMD_RETENTION),
+       .statechange = 1,
+       .logicretstate = 1,
+};
+
+static const struct omap_rst_map rst_map_0[] = {
+       { .rst = 0, .st = 0 },
+       { .rst = -1 },
+};
+
+static const struct omap_rst_map rst_map_01[] = {
+       { .rst = 0, .st = 0 },
+       { .rst = 1, .st = 1 },
+       { .rst = -1 },
+};
+
+static const struct omap_rst_map rst_map_012[] = {
+       { .rst = 0, .st = 0 },
+       { .rst = 1, .st = 1 },
+       { .rst = 2, .st = 2 },
+       { .rst = -1 },
+};
+
+static const struct omap_prm_data omap4_prm_data[] = {
+       {
+               .name = "mpu", .base = 0x4a306300,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
+       },
+       {
+               .name = "tesla", .base = 0x4a306400,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
+               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
+       },
+       {
+               .name = "abe", .base = 0x4a306500,
+               .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_all,
+       },
+       {
+               .name = "always_on_core", .base = 0x4a306600,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
+       },
+       {
+               .name = "core", .base = 0x4a306700,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
+               .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ducati",
+               .rstmap = rst_map_012,
+               .flags = OMAP_PRM_RET_WHEN_IDLE,
+       },
+       {
+               .name = "ivahd", .base = 0x4a306f00,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
+               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012
+       },
+       {
+               .name = "cam", .base = 0x4a307000,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+       },
+       {
+               .name = "dss", .base = 0x4a307100,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact
+       },
+       {
+               .name = "gfx", .base = 0x4a307200,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
+       },
+       {
+               .name = "l3init", .base = 0x4a307300,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton
+       },
+       {
+               .name = "l4per", .base = 0x4a307400,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
+               .flags = OMAP_PRM_RET_WHEN_IDLE,
+       },
+       {
+               .name = "cefuse", .base = 0x4a307600,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
+       },
+       {
+               .name = "wkup", .base = 0x4a307700,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon
+       },
+       {
+               .name = "emu", .base = 0x4a307900,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
+       },
+       {
+               .name = "device", .base = 0x4a307b00,
+               .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01,
+               .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
+       },
+       { },
+};
+
+static const struct omap_prm_data omap5_prm_data[] = {
+       {
+               .name = "mpu", .base = 0x4ae06300,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
+       },
+       {
+               .name = "dsp", .base = 0x4ae06400,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
+               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
+       },
+       {
+               .name = "abe", .base = 0x4ae06500,
+               .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_nooff,
+       },
+       {
+               .name = "coreaon", .base = 0x4ae06600,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon
+       },
+       {
+               .name = "core", .base = 0x4ae06700,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
+               .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ipu",
+               .rstmap = rst_map_012
+       },
+       {
+               .name = "iva", .base = 0x4ae07200,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
+               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012
+       },
+       {
+               .name = "cam", .base = 0x4ae07300,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
+       },
+       {
+               .name = "dss", .base = 0x4ae07400,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact
+       },
+       {
+               .name = "gpu", .base = 0x4ae07500,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
+       },
+       {
+               .name = "l3init", .base = 0x4ae07600,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton
+       },
+       {
+               .name = "custefuse", .base = 0x4ae07700,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
+       },
+       {
+               .name = "wkupaon", .base = 0x4ae07800,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon
+       },
+       {
+               .name = "emu", .base = 0x4ae07a00,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto
+       },
+       {
+               .name = "device", .base = 0x4ae07c00,
+               .rstctrl = 0x0, .rstst = 0x4, .rstmap = rst_map_01,
+               .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
+       },
+       { },
+};
+
+static const struct omap_prm_data dra7_prm_data[] = {
+       {
+               .name = "mpu", .base = 0x4ae06300,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton,
+       },
+       {
+               .name = "dsp1", .base = 0x4ae06400,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01,
+       },
+       {
+               .name = "ipu", .base = 0x4ae06500,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012,
+               .clkdm_name = "ipu1"
+       },
+       {
+               .name = "coreaon", .base = 0x4ae06628,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
+       },
+       {
+               .name = "core", .base = 0x4ae06700,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
+               .rstctrl = 0x210, .rstst = 0x214, .rstmap = rst_map_012,
+               .clkdm_name = "ipu2"
+       },
+       {
+               .name = "iva", .base = 0x4ae06f00,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012,
+       },
+       {
+               .name = "cam", .base = 0x4ae07000,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+       },
+       {
+               .name = "dss", .base = 0x4ae07100,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+       },
+       {
+               .name = "gpu", .base = 0x4ae07200,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+       },
+       {
+               .name = "l3init", .base = 0x4ae07300,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
+               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01,
+               .clkdm_name = "pcie"
+       },
+       {
+               .name = "l4per", .base = 0x4ae07400,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
+       },
+       {
+               .name = "custefuse", .base = 0x4ae07600,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+       },
+       {
+               .name = "wkupaon", .base = 0x4ae07724,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
+       },
+       {
+               .name = "emu", .base = 0x4ae07900,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+       },
+       {
+               .name = "dsp2", .base = 0x4ae07b00,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
+       },
+       {
+               .name = "eve1", .base = 0x4ae07b40,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
+       },
+       {
+               .name = "eve2", .base = 0x4ae07b80,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
+       },
+       {
+               .name = "eve3", .base = 0x4ae07bc0,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
+       },
+       {
+               .name = "eve4", .base = 0x4ae07c00,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01
+       },
+       {
+               .name = "rtc", .base = 0x4ae07c60,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
+       },
+       {
+               .name = "vpe", .base = 0x4ae07c80,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+       },
+       { },
+};
+
+static const struct omap_rst_map am3_per_rst_map[] = {
+       { .rst = 1 },
+       { .rst = -1 },
+};
+
+static const struct omap_rst_map am3_wkup_rst_map[] = {
+       { .rst = 3, .st = 5 },
+       { .rst = -1 },
+};
+
+static const struct omap_prm_data am3_prm_data[] = {
+       {
+               .name = "per", .base = 0x44e00c00,
+               .pwrstctrl = 0xc, .pwrstst = 0x8, .dmap = &omap_prm_noinact,
+               .rstctrl = 0x0, .rstmap = am3_per_rst_map,
+               .flags = OMAP_PRM_HAS_RSTCTRL, .clkdm_name = "pruss_ocp"
+       },
+       {
+               .name = "wkup", .base = 0x44e00d00,
+               .pwrstctrl = 0x4, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
+               .rstctrl = 0x0, .rstst = 0xc, .rstmap = am3_wkup_rst_map,
+               .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
+       },
+       {
+               .name = "mpu", .base = 0x44e00e00,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
+       },
+       {
+               .name = "device", .base = 0x44e00f00,
+               .rstctrl = 0x0, .rstst = 0x8, .rstmap = rst_map_01,
+               .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
+       },
+       {
+               .name = "rtc", .base = 0x44e01000,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
+       },
+       {
+               .name = "gfx", .base = 0x44e01100,
+               .pwrstctrl = 0, .pwrstst = 0x10, .dmap = &omap_prm_noinact,
+               .rstctrl = 0x4, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3",
+       },
+       {
+               .name = "cefuse", .base = 0x44e01200,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+       },
+       { },
+};
+
+static const struct omap_rst_map am4_per_rst_map[] = {
+       { .rst = 1, .st = 0 },
+       { .rst = -1 },
+};
+
+static const struct omap_rst_map am4_device_rst_map[] = {
+       { .rst = 0, .st = 1 },
+       { .rst = 1, .st = 0 },
+       { .rst = -1 },
+};
+
+static const struct omap_prm_data am4_prm_data[] = {
+       {
+               .name = "mpu", .base = 0x44df0300,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
+       },
+       {
+               .name = "gfx", .base = 0x44df0400,
+               .pwrstctrl = 0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+               .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_0, .clkdm_name = "gfx_l3",
+       },
+       {
+               .name = "rtc", .base = 0x44df0500,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
+       },
+       {
+               .name = "tamper", .base = 0x44df0600,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
+       },
+       {
+               .name = "cefuse", .base = 0x44df0700,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_onoff_noauto,
+       },
+       {
+               .name = "per", .base = 0x44df0800,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_noinact,
+               .rstctrl = 0x10, .rstst = 0x14, .rstmap = am4_per_rst_map,
+               .clkdm_name = "pruss_ocp"
+       },
+       {
+               .name = "wkup", .base = 0x44df2000,
+               .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon,
+               .rstctrl = 0x10, .rstst = 0x14, .rstmap = am3_wkup_rst_map,
+               .flags = OMAP_PRM_HAS_NO_CLKDM
+       },
+       {
+               .name = "device", .base = 0x44df4000,
+               .rstctrl = 0x0, .rstst = 0x4, .rstmap = am4_device_rst_map,
+               .flags = OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_NO_CLKDM
+       },
+       { },
+};
+
+static const struct of_device_id omap_prm_id_table[] = {
+       { .compatible = "ti,omap4-prm-inst", .data = omap4_prm_data },
+       { .compatible = "ti,omap5-prm-inst", .data = omap5_prm_data },
+       { .compatible = "ti,dra7-prm-inst", .data = dra7_prm_data },
+       { .compatible = "ti,am3-prm-inst", .data = am3_prm_data },
+       { .compatible = "ti,am4-prm-inst", .data = am4_prm_data },
+       { },
+};
+
+#ifdef DEBUG
+static void omap_prm_domain_show_state(struct omap_prm_domain *prmd,
+                                      const char *desc)
+{
+       dev_dbg(prmd->dev, "%s %s: %08x/%08x\n",
+               prmd->pd.name, desc,
+               readl_relaxed(prmd->prm->base + prmd->pwrstctrl),
+               readl_relaxed(prmd->prm->base + prmd->pwrstst));
+}
+#else
+static inline void omap_prm_domain_show_state(struct omap_prm_domain *prmd,
+                                             const char *desc)
+{
+}
+#endif
+
+static int omap_prm_domain_power_on(struct generic_pm_domain *domain)
+{
+       struct omap_prm_domain *prmd;
+       int ret;
+       u32 v, mode;
+
+       prmd = genpd_to_prm_domain(domain);
+       if (!prmd->cap)
+               return 0;
+
+       omap_prm_domain_show_state(prmd, "on: previous state");
+
+       if (prmd->pwrstctrl_saved)
+               v = prmd->pwrstctrl_saved;
+       else
+               v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl);
+
+       if (prmd->prm->data->flags & OMAP_PRM_RET_WHEN_IDLE)
+               mode = OMAP_PRMD_RETENTION;
+       else
+               mode = OMAP_PRMD_ON_ACTIVE;
+
+       writel_relaxed((v & ~PRM_POWERSTATE_MASK) | mode,
+                      prmd->prm->base + prmd->pwrstctrl);
+
+       /* wait for the transition bit to get cleared */
+       ret = readl_relaxed_poll_timeout(prmd->prm->base + prmd->pwrstst,
+                                        v, !(v & PRM_ST_INTRANSITION), 1,
+                                        PRM_STATE_MAX_WAIT);
+       if (ret)
+               dev_err(prmd->dev, "%s: %s timed out\n",
+                       prmd->pd.name, __func__);
+
+       omap_prm_domain_show_state(prmd, "on: new state");
+
+       return ret;
+}
+
+/* No need to check for holes in the mask for the lowest mode */
+static int omap_prm_domain_find_lowest(struct omap_prm_domain *prmd)
+{
+       return __ffs(prmd->cap->usable_modes);
+}
+
+static int omap_prm_domain_power_off(struct generic_pm_domain *domain)
+{
+       struct omap_prm_domain *prmd;
+       int ret;
+       u32 v;
+
+       prmd = genpd_to_prm_domain(domain);
+       if (!prmd->cap)
+               return 0;
+
+       omap_prm_domain_show_state(prmd, "off: previous state");
+
+       v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl);
+       prmd->pwrstctrl_saved = v;
+
+       v &= ~PRM_POWERSTATE_MASK;
+       v |= omap_prm_domain_find_lowest(prmd);
+
+       if (prmd->cap->statechange)
+               v |= PRM_LOWPOWERSTATECHANGE;
+       if (prmd->cap->logicretstate)
+               v &= ~PRM_LOGICRETSTATE;
+       else
+               v |= PRM_LOGICRETSTATE;
+
+       writel_relaxed(v, prmd->prm->base + prmd->pwrstctrl);
+
+       /* wait for the transition bit to get cleared */
+       ret = readl_relaxed_poll_timeout(prmd->prm->base + prmd->pwrstst,
+                                        v, !(v & PRM_ST_INTRANSITION), 1,
+                                        PRM_STATE_MAX_WAIT);
+       if (ret)
+               dev_warn(prmd->dev, "%s: %s timed out\n",
+                        __func__, prmd->pd.name);
+
+       omap_prm_domain_show_state(prmd, "off: new state");
+
+       return 0;
+}
+
+/*
+ * Note that ti-sysc already manages the module clocks separately so
+ * no need to manage those. Interconnect instances need clocks managed
+ * for simple-pm-bus.
+ */
+static int omap_prm_domain_attach_clock(struct device *dev,
+                                       struct omap_prm_domain *prmd)
+{
+       struct device_node *np = dev->of_node;
+       int error;
+
+       if (!of_device_is_compatible(np, "simple-pm-bus"))
+               return 0;
+
+       if (!of_property_read_bool(np, "clocks"))
+               return 0;
+
+       error = pm_clk_create(dev);
+       if (error)
+               return error;
+
+       error = of_pm_clk_add_clks(dev);
+       if (error < 0) {
+               pm_clk_destroy(dev);
+               return error;
+       }
+
+       prmd->uses_pm_clk = 1;
+
+       return 0;
+}
+
+static int omap_prm_domain_attach_dev(struct generic_pm_domain *domain,
+                                     struct device *dev)
+{
+       struct generic_pm_domain_data *genpd_data;
+       struct of_phandle_args pd_args;
+       struct omap_prm_domain *prmd;
+       struct device_node *np;
+       int ret;
+
+       prmd = genpd_to_prm_domain(domain);
+       np = dev->of_node;
+
+       ret = of_parse_phandle_with_args(np, "power-domains",
+                                        "#power-domain-cells", 0, &pd_args);
+       if (ret < 0)
+               return ret;
+
+       if (pd_args.args_count != 0)
+               dev_warn(dev, "%s: unusupported #power-domain-cells: %i\n",
+                        prmd->pd.name, pd_args.args_count);
+
+       genpd_data = dev_gpd_data(dev);
+       genpd_data->data = NULL;
+
+       ret = omap_prm_domain_attach_clock(dev, prmd);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static void omap_prm_domain_detach_dev(struct generic_pm_domain *domain,
+                                      struct device *dev)
+{
+       struct generic_pm_domain_data *genpd_data;
+       struct omap_prm_domain *prmd;
+
+       prmd = genpd_to_prm_domain(domain);
+       if (prmd->uses_pm_clk)
+               pm_clk_destroy(dev);
+       genpd_data = dev_gpd_data(dev);
+       genpd_data->data = NULL;
+}
+
+static int omap_prm_domain_init(struct device *dev, struct omap_prm *prm)
+{
+       struct omap_prm_domain *prmd;
+       struct device_node *np = dev->of_node;
+       const struct omap_prm_data *data;
+       const char *name;
+       int error;
+
+       if (!of_property_present(dev->of_node, "#power-domain-cells"))
+               return 0;
+
+       of_node_put(dev->of_node);
+
+       prmd = devm_kzalloc(dev, sizeof(*prmd), GFP_KERNEL);
+       if (!prmd)
+               return -ENOMEM;
+
+       data = prm->data;
+       name = devm_kasprintf(dev, GFP_KERNEL, "prm_%s",
+                             data->name);
+
+       prmd->dev = dev;
+       prmd->prm = prm;
+       prmd->cap = prmd->prm->data->dmap;
+       prmd->pwrstctrl = prmd->prm->data->pwrstctrl;
+       prmd->pwrstst = prmd->prm->data->pwrstst;
+
+       prmd->pd.name = name;
+       prmd->pd.power_on = omap_prm_domain_power_on;
+       prmd->pd.power_off = omap_prm_domain_power_off;
+       prmd->pd.attach_dev = omap_prm_domain_attach_dev;
+       prmd->pd.detach_dev = omap_prm_domain_detach_dev;
+       prmd->pd.flags = GENPD_FLAG_PM_CLK;
+
+       pm_genpd_init(&prmd->pd, NULL, true);
+       error = of_genpd_add_provider_simple(np, &prmd->pd);
+       if (error)
+               pm_genpd_remove(&prmd->pd);
+       else
+               prm->prmd = prmd;
+
+       return error;
+}
+
+static bool _is_valid_reset(struct omap_reset_data *reset, unsigned long id)
+{
+       if (reset->mask & BIT(id))
+               return true;
+
+       return false;
+}
+
+static int omap_reset_get_st_bit(struct omap_reset_data *reset,
+                                unsigned long id)
+{
+       const struct omap_rst_map *map = reset->prm->data->rstmap;
+
+       while (map->rst >= 0) {
+               if (map->rst == id)
+                       return map->st;
+
+               map++;
+       }
+
+       return id;
+}
+
+static int omap_reset_status(struct reset_controller_dev *rcdev,
+                            unsigned long id)
+{
+       struct omap_reset_data *reset = to_omap_reset_data(rcdev);
+       u32 v;
+       int st_bit = omap_reset_get_st_bit(reset, id);
+       bool has_rstst = reset->prm->data->rstst ||
+               (reset->prm->data->flags & OMAP_PRM_HAS_RSTST);
+
+       /* Check if we have rstst */
+       if (!has_rstst)
+               return -ENOTSUPP;
+
+       /* Check if hw reset line is asserted */
+       v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
+       if (v & BIT(id))
+               return 1;
+
+       /*
+        * Check reset status, high value means reset sequence has been
+        * completed successfully so we can return 0 here (reset deasserted)
+        */
+       v = readl_relaxed(reset->prm->base + reset->prm->data->rstst);
+       v >>= st_bit;
+       v &= 1;
+
+       return !v;
+}
+
+static int omap_reset_assert(struct reset_controller_dev *rcdev,
+                            unsigned long id)
+{
+       struct omap_reset_data *reset = to_omap_reset_data(rcdev);
+       u32 v;
+       unsigned long flags;
+
+       /* assert the reset control line */
+       spin_lock_irqsave(&reset->lock, flags);
+       v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
+       v |= 1 << id;
+       writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl);
+       spin_unlock_irqrestore(&reset->lock, flags);
+
+       return 0;
+}
+
+static int omap_reset_deassert(struct reset_controller_dev *rcdev,
+                              unsigned long id)
+{
+       struct omap_reset_data *reset = to_omap_reset_data(rcdev);
+       u32 v;
+       int st_bit;
+       bool has_rstst;
+       unsigned long flags;
+       struct ti_prm_platform_data *pdata = dev_get_platdata(reset->dev);
+       int ret = 0;
+
+       /* Nothing to do if the reset is already deasserted */
+       if (!omap_reset_status(rcdev, id))
+               return 0;
+
+       has_rstst = reset->prm->data->rstst ||
+               (reset->prm->data->flags & OMAP_PRM_HAS_RSTST);
+
+       if (has_rstst) {
+               st_bit = omap_reset_get_st_bit(reset, id);
+
+               /* Clear the reset status by writing 1 to the status bit */
+               v = 1 << st_bit;
+               writel_relaxed(v, reset->prm->base + reset->prm->data->rstst);
+       }
+
+       if (reset->clkdm)
+               pdata->clkdm_deny_idle(reset->clkdm);
+
+       /* de-assert the reset control line */
+       spin_lock_irqsave(&reset->lock, flags);
+       v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
+       v &= ~(1 << id);
+       writel_relaxed(v, reset->prm->base + reset->prm->data->rstctrl);
+       spin_unlock_irqrestore(&reset->lock, flags);
+
+       /* wait for the reset bit to clear */
+       ret = readl_relaxed_poll_timeout_atomic(reset->prm->base +
+                                               reset->prm->data->rstctrl,
+                                               v, !(v & BIT(id)), 1,
+                                               OMAP_RESET_MAX_WAIT);
+       if (ret)
+               pr_err("%s: timedout waiting for %s:%lu\n", __func__,
+                      reset->prm->data->name, id);
+
+       /* wait for the status to be set */
+       if (has_rstst) {
+               ret = readl_relaxed_poll_timeout_atomic(reset->prm->base +
+                                                reset->prm->data->rstst,
+                                                v, v & BIT(st_bit), 1,
+                                                OMAP_RESET_MAX_WAIT);
+               if (ret)
+                       pr_err("%s: timedout waiting for %s:%lu\n", __func__,
+                              reset->prm->data->name, id);
+       }
+
+       if (reset->clkdm)
+               pdata->clkdm_allow_idle(reset->clkdm);
+
+       return ret;
+}
+
+static const struct reset_control_ops omap_reset_ops = {
+       .assert         = omap_reset_assert,
+       .deassert       = omap_reset_deassert,
+       .status         = omap_reset_status,
+};
+
+static int omap_prm_reset_xlate(struct reset_controller_dev *rcdev,
+                               const struct of_phandle_args *reset_spec)
+{
+       struct omap_reset_data *reset = to_omap_reset_data(rcdev);
+
+       if (!_is_valid_reset(reset, reset_spec->args[0]))
+               return -EINVAL;
+
+       return reset_spec->args[0];
+}
+
+static int omap_prm_reset_init(struct platform_device *pdev,
+                              struct omap_prm *prm)
+{
+       struct omap_reset_data *reset;
+       const struct omap_rst_map *map;
+       struct ti_prm_platform_data *pdata = dev_get_platdata(&pdev->dev);
+       char buf[32];
+       u32 v;
+
+       /*
+        * Check if we have controllable resets. If either rstctrl is non-zero
+        * or OMAP_PRM_HAS_RSTCTRL flag is set, we have reset control register
+        * for the domain.
+        */
+       if (!prm->data->rstctrl && !(prm->data->flags & OMAP_PRM_HAS_RSTCTRL))
+               return 0;
+
+       /* Check if we have the pdata callbacks in place */
+       if (!pdata || !pdata->clkdm_lookup || !pdata->clkdm_deny_idle ||
+           !pdata->clkdm_allow_idle)
+               return -EINVAL;
+
+       map = prm->data->rstmap;
+       if (!map)
+               return -EINVAL;
+
+       reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
+       if (!reset)
+               return -ENOMEM;
+
+       reset->rcdev.owner = THIS_MODULE;
+       reset->rcdev.ops = &omap_reset_ops;
+       reset->rcdev.of_node = pdev->dev.of_node;
+       reset->rcdev.nr_resets = OMAP_MAX_RESETS;
+       reset->rcdev.of_xlate = omap_prm_reset_xlate;
+       reset->rcdev.of_reset_n_cells = 1;
+       reset->dev = &pdev->dev;
+       spin_lock_init(&reset->lock);
+
+       reset->prm = prm;
+
+       sprintf(buf, "%s_clkdm", prm->data->clkdm_name ? prm->data->clkdm_name :
+               prm->data->name);
+
+       if (!(prm->data->flags & OMAP_PRM_HAS_NO_CLKDM)) {
+               reset->clkdm = pdata->clkdm_lookup(buf);
+               if (!reset->clkdm)
+                       return -EINVAL;
+       }
+
+       while (map->rst >= 0) {
+               reset->mask |= BIT(map->rst);
+               map++;
+       }
+
+       /* Quirk handling to assert rst_map_012 bits on reset and avoid errors */
+       if (prm->data->rstmap == rst_map_012) {
+               v = readl_relaxed(reset->prm->base + reset->prm->data->rstctrl);
+               if ((v & reset->mask) != reset->mask) {
+                       dev_dbg(&pdev->dev, "Asserting all resets: %08x\n", v);
+                       writel_relaxed(reset->mask, reset->prm->base +
+                                      reset->prm->data->rstctrl);
+               }
+       }
+
+       return devm_reset_controller_register(&pdev->dev, &reset->rcdev);
+}
+
+static int omap_prm_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       const struct omap_prm_data *data;
+       struct omap_prm *prm;
+       int ret;
+
+       data = of_device_get_match_data(&pdev->dev);
+       if (!data)
+               return -ENOTSUPP;
+
+       prm = devm_kzalloc(&pdev->dev, sizeof(*prm), GFP_KERNEL);
+       if (!prm)
+               return -ENOMEM;
+
+       prm->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+       if (IS_ERR(prm->base))
+               return PTR_ERR(prm->base);
+
+       while (data->base != res->start) {
+               if (!data->base)
+                       return -EINVAL;
+               data++;
+       }
+
+       prm->data = data;
+
+       ret = omap_prm_domain_init(&pdev->dev, prm);
+       if (ret)
+               return ret;
+
+       ret = omap_prm_reset_init(pdev, prm);
+       if (ret)
+               goto err_domain;
+
+       return 0;
+
+err_domain:
+       of_genpd_del_provider(pdev->dev.of_node);
+       pm_genpd_remove(&prm->prmd->pd);
+
+       return ret;
+}
+
+static struct platform_driver omap_prm_driver = {
+       .probe = omap_prm_probe,
+       .driver = {
+               .name           = KBUILD_MODNAME,
+               .of_match_table = omap_prm_id_table,
+       },
+};
+builtin_platform_driver(omap_prm_driver);
diff --git a/drivers/pmdomain/ti/ti_sci_pm_domains.c b/drivers/pmdomain/ti/ti_sci_pm_domains.c
new file mode 100644 (file)
index 0000000..3464510
--- /dev/null
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * TI SCI Generic Power Domain Driver
+ *
+ * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
+ *     J Keerthy <j-keerthy@ti.com>
+ *     Dave Gerlach <d-gerlach@ti.com>
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/soc/ti/ti_sci_protocol.h>
+#include <dt-bindings/soc/ti,sci_pm_domain.h>
+
+/**
+ * struct ti_sci_genpd_provider: holds common TI SCI genpd provider data
+ * @ti_sci: handle to TI SCI protocol driver that provides ops to
+ *         communicate with system control processor.
+ * @dev: pointer to dev for the driver for devm allocs
+ * @pd_list: list of all the power domains on the device
+ * @data: onecell data for genpd core
+ */
+struct ti_sci_genpd_provider {
+       const struct ti_sci_handle *ti_sci;
+       struct device *dev;
+       struct list_head pd_list;
+       struct genpd_onecell_data data;
+};
+
+/**
+ * struct ti_sci_pm_domain: TI specific data needed for power domain
+ * @idx: index of the device that identifies it with the system
+ *      control processor.
+ * @exclusive: Permissions for exclusive request or shared request of the
+ *            device.
+ * @pd: generic_pm_domain for use with the genpd framework
+ * @node: link for the genpd list
+ * @parent: link to the parent TI SCI genpd provider
+ */
+struct ti_sci_pm_domain {
+       int idx;
+       u8 exclusive;
+       struct generic_pm_domain pd;
+       struct list_head node;
+       struct ti_sci_genpd_provider *parent;
+};
+
+#define genpd_to_ti_sci_pd(gpd) container_of(gpd, struct ti_sci_pm_domain, pd)
+
+/*
+ * ti_sci_pd_power_off(): genpd power down hook
+ * @domain: pointer to the powerdomain to power off
+ */
+static int ti_sci_pd_power_off(struct generic_pm_domain *domain)
+{
+       struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(domain);
+       const struct ti_sci_handle *ti_sci = pd->parent->ti_sci;
+
+       return ti_sci->ops.dev_ops.put_device(ti_sci, pd->idx);
+}
+
+/*
+ * ti_sci_pd_power_on(): genpd power up hook
+ * @domain: pointer to the powerdomain to power on
+ */
+static int ti_sci_pd_power_on(struct generic_pm_domain *domain)
+{
+       struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(domain);
+       const struct ti_sci_handle *ti_sci = pd->parent->ti_sci;
+
+       if (pd->exclusive)
+               return ti_sci->ops.dev_ops.get_device_exclusive(ti_sci,
+                                                               pd->idx);
+       else
+               return ti_sci->ops.dev_ops.get_device(ti_sci, pd->idx);
+}
+
+/*
+ * ti_sci_pd_xlate(): translation service for TI SCI genpds
+ * @genpdspec: DT identification data for the genpd
+ * @data: genpd core data for all the powerdomains on the device
+ */
+static struct generic_pm_domain *ti_sci_pd_xlate(
+                                       struct of_phandle_args *genpdspec,
+                                       void *data)
+{
+       struct genpd_onecell_data *genpd_data = data;
+       unsigned int idx = genpdspec->args[0];
+
+       if (genpdspec->args_count != 1 && genpdspec->args_count != 2)
+               return ERR_PTR(-EINVAL);
+
+       if (idx >= genpd_data->num_domains) {
+               pr_err("%s: invalid domain index %u\n", __func__, idx);
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (!genpd_data->domains[idx])
+               return ERR_PTR(-ENOENT);
+
+       genpd_to_ti_sci_pd(genpd_data->domains[idx])->exclusive =
+               genpdspec->args[1];
+
+       return genpd_data->domains[idx];
+}
+
+static const struct of_device_id ti_sci_pm_domain_matches[] = {
+       { .compatible = "ti,sci-pm-domain", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, ti_sci_pm_domain_matches);
+
+static int ti_sci_pm_domain_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct ti_sci_genpd_provider *pd_provider;
+       struct ti_sci_pm_domain *pd;
+       struct device_node *np;
+       struct of_phandle_args args;
+       int ret;
+       u32 max_id = 0;
+       int index;
+
+       pd_provider = devm_kzalloc(dev, sizeof(*pd_provider), GFP_KERNEL);
+       if (!pd_provider)
+               return -ENOMEM;
+
+       pd_provider->ti_sci = devm_ti_sci_get_handle(dev);
+       if (IS_ERR(pd_provider->ti_sci))
+               return PTR_ERR(pd_provider->ti_sci);
+
+       pd_provider->dev = dev;
+
+       INIT_LIST_HEAD(&pd_provider->pd_list);
+
+       /* Find highest device ID used for power domains */
+       for_each_node_with_property(np, "power-domains") {
+               index = 0;
+
+               while (1) {
+                       ret = of_parse_phandle_with_args(np, "power-domains",
+                                                        "#power-domain-cells",
+                                                        index, &args);
+                       if (ret)
+                               break;
+
+                       if (args.args_count >= 1 && args.np == dev->of_node) {
+                               if (args.args[0] > max_id)
+                                       max_id = args.args[0];
+
+                               pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+                               if (!pd)
+                                       return -ENOMEM;
+
+                               pd->pd.name = devm_kasprintf(dev, GFP_KERNEL,
+                                                            "pd:%d",
+                                                            args.args[0]);
+                               if (!pd->pd.name)
+                                       return -ENOMEM;
+
+                               pd->pd.power_off = ti_sci_pd_power_off;
+                               pd->pd.power_on = ti_sci_pd_power_on;
+                               pd->idx = args.args[0];
+                               pd->parent = pd_provider;
+
+                               pm_genpd_init(&pd->pd, NULL, true);
+
+                               list_add(&pd->node, &pd_provider->pd_list);
+                       }
+                       index++;
+               }
+       }
+
+       pd_provider->data.domains =
+               devm_kcalloc(dev, max_id + 1,
+                            sizeof(*pd_provider->data.domains),
+                            GFP_KERNEL);
+       if (!pd_provider->data.domains)
+               return -ENOMEM;
+
+       pd_provider->data.num_domains = max_id + 1;
+       pd_provider->data.xlate = ti_sci_pd_xlate;
+
+       list_for_each_entry(pd, &pd_provider->pd_list, node)
+               pd_provider->data.domains[pd->idx] = &pd->pd;
+
+       return of_genpd_add_provider_onecell(dev->of_node, &pd_provider->data);
+}
+
+static struct platform_driver ti_sci_pm_domains_driver = {
+       .probe = ti_sci_pm_domain_probe,
+       .driver = {
+               .name = "ti_sci_pm_domains",
+               .of_match_table = ti_sci_pm_domain_matches,
+       },
+};
+module_platform_driver(ti_sci_pm_domains_driver);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TI System Control Interface (SCI) Power Domain driver");
+MODULE_AUTHOR("Dave Gerlach");
diff --git a/drivers/pmdomain/xilinx/Makefile b/drivers/pmdomain/xilinx/Makefile
new file mode 100644 (file)
index 0000000..a706ab6
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_ZYNQMP_PM_DOMAINS)                += zynqmp-pm-domains.o
diff --git a/drivers/pmdomain/xilinx/zynqmp-pm-domains.c b/drivers/pmdomain/xilinx/zynqmp-pm-domains.c
new file mode 100644 (file)
index 0000000..69d03ad
--- /dev/null
@@ -0,0 +1,322 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ZynqMP Generic PM domain support
+ *
+ *  Copyright (C) 2015-2019 Xilinx, Inc.
+ *
+ *  Davorin Mista <davorin.mista@aggios.com>
+ *  Jolly Shah <jollys@xilinx.com>
+ *  Rajan Vaja <rajan.vaja@xilinx.com>
+ */
+
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+
+#include <linux/firmware/xlnx-zynqmp.h>
+
+#define ZYNQMP_NUM_DOMAINS             (100)
+
+static int min_capability;
+
+/**
+ * struct zynqmp_pm_domain - Wrapper around struct generic_pm_domain
+ * @gpd:               Generic power domain
+ * @node_id:           PM node ID corresponding to device inside PM domain
+ * @requested:         The PM node mapped to the PM domain has been requested
+ */
+struct zynqmp_pm_domain {
+       struct generic_pm_domain gpd;
+       u32 node_id;
+       bool requested;
+};
+
+#define to_zynqmp_pm_domain(pm_domain) \
+       container_of(pm_domain, struct zynqmp_pm_domain, gpd)
+
+/**
+ * zynqmp_gpd_is_active_wakeup_path() - Check if device is in wakeup source
+ *                                     path
+ * @dev:       Device to check for wakeup source path
+ * @not_used:  Data member (not required)
+ *
+ * This function is checks device's child hierarchy and checks if any device is
+ * set as wakeup source.
+ *
+ * Return: 1 if device is in wakeup source path else 0
+ */
+static int zynqmp_gpd_is_active_wakeup_path(struct device *dev, void *not_used)
+{
+       int may_wakeup;
+
+       may_wakeup = device_may_wakeup(dev);
+       if (may_wakeup)
+               return may_wakeup;
+
+       return device_for_each_child(dev, NULL,
+                       zynqmp_gpd_is_active_wakeup_path);
+}
+
+/**
+ * zynqmp_gpd_power_on() - Power on PM domain
+ * @domain:    Generic PM domain
+ *
+ * This function is called before devices inside a PM domain are resumed, to
+ * power on PM domain.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int zynqmp_gpd_power_on(struct generic_pm_domain *domain)
+{
+       struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain);
+       int ret;
+
+       ret = zynqmp_pm_set_requirement(pd->node_id,
+                                       ZYNQMP_PM_CAPABILITY_ACCESS,
+                                       ZYNQMP_PM_MAX_QOS,
+                                       ZYNQMP_PM_REQUEST_ACK_BLOCKING);
+       if (ret) {
+               dev_err(&domain->dev,
+                       "failed to set requirement to 0x%x for PM node id %d: %d\n",
+                       ZYNQMP_PM_CAPABILITY_ACCESS, pd->node_id, ret);
+               return ret;
+       }
+
+       dev_dbg(&domain->dev, "set requirement to 0x%x for PM node id %d\n",
+               ZYNQMP_PM_CAPABILITY_ACCESS, pd->node_id);
+
+       return 0;
+}
+
+/**
+ * zynqmp_gpd_power_off() - Power off PM domain
+ * @domain:    Generic PM domain
+ *
+ * This function is called after devices inside a PM domain are suspended, to
+ * power off PM domain.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int zynqmp_gpd_power_off(struct generic_pm_domain *domain)
+{
+       struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain);
+       int ret;
+       struct pm_domain_data *pdd, *tmp;
+       u32 capabilities = min_capability;
+       bool may_wakeup;
+
+       /* If domain is already released there is nothing to be done */
+       if (!pd->requested) {
+               dev_dbg(&domain->dev, "PM node id %d is already released\n",
+                       pd->node_id);
+               return 0;
+       }
+
+       list_for_each_entry_safe(pdd, tmp, &domain->dev_list, list_node) {
+               /* If device is in wakeup path, set capability to WAKEUP */
+               may_wakeup = zynqmp_gpd_is_active_wakeup_path(pdd->dev, NULL);
+               if (may_wakeup) {
+                       dev_dbg(pdd->dev, "device is in wakeup path in %s\n",
+                               domain->name);
+                       capabilities = ZYNQMP_PM_CAPABILITY_WAKEUP;
+                       break;
+               }
+       }
+
+       ret = zynqmp_pm_set_requirement(pd->node_id, capabilities, 0,
+                                       ZYNQMP_PM_REQUEST_ACK_NO);
+       if (ret) {
+               dev_err(&domain->dev,
+                       "failed to set requirement to 0x%x for PM node id %d: %d\n",
+                       capabilities, pd->node_id, ret);
+               return ret;
+       }
+
+       dev_dbg(&domain->dev, "set requirement to 0x%x for PM node id %d\n",
+               capabilities, pd->node_id);
+
+       return 0;
+}
+
+/**
+ * zynqmp_gpd_attach_dev() - Attach device to the PM domain
+ * @domain:    Generic PM domain
+ * @dev:       Device to attach
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int zynqmp_gpd_attach_dev(struct generic_pm_domain *domain,
+                                struct device *dev)
+{
+       struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain);
+       struct device_link *link;
+       int ret;
+
+       link = device_link_add(dev, &domain->dev, DL_FLAG_SYNC_STATE_ONLY);
+       if (!link)
+               dev_dbg(&domain->dev, "failed to create device link for %s\n",
+                       dev_name(dev));
+
+       /* If this is not the first device to attach there is nothing to do */
+       if (domain->device_count)
+               return 0;
+
+       ret = zynqmp_pm_request_node(pd->node_id, 0, 0,
+                                    ZYNQMP_PM_REQUEST_ACK_BLOCKING);
+       if (ret) {
+               dev_err(&domain->dev, "%s request failed for node %d: %d\n",
+                       domain->name, pd->node_id, ret);
+               return ret;
+       }
+
+       pd->requested = true;
+
+       dev_dbg(&domain->dev, "%s requested PM node id %d\n",
+               dev_name(dev), pd->node_id);
+
+       return 0;
+}
+
+/**
+ * zynqmp_gpd_detach_dev() - Detach device from the PM domain
+ * @domain:    Generic PM domain
+ * @dev:       Device to detach
+ */
+static void zynqmp_gpd_detach_dev(struct generic_pm_domain *domain,
+                                 struct device *dev)
+{
+       struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain);
+       int ret;
+
+       /* If this is not the last device to detach there is nothing to do */
+       if (domain->device_count)
+               return;
+
+       ret = zynqmp_pm_release_node(pd->node_id);
+       if (ret) {
+               dev_err(&domain->dev, "failed to release PM node id %d: %d\n",
+                       pd->node_id, ret);
+               return;
+       }
+
+       pd->requested = false;
+
+       dev_dbg(&domain->dev, "%s released PM node id %d\n",
+               dev_name(dev), pd->node_id);
+}
+
+static struct generic_pm_domain *zynqmp_gpd_xlate
+                               (struct of_phandle_args *genpdspec, void *data)
+{
+       struct genpd_onecell_data *genpd_data = data;
+       unsigned int i, idx = genpdspec->args[0];
+       struct zynqmp_pm_domain *pd;
+
+       pd = to_zynqmp_pm_domain(genpd_data->domains[0]);
+
+       if (genpdspec->args_count != 1)
+               return ERR_PTR(-EINVAL);
+
+       /* Check for existing pm domains */
+       for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++) {
+               if (pd[i].node_id == idx)
+                       goto done;
+       }
+
+       /*
+        * Add index in empty node_id of power domain list as no existing
+        * power domain found for current index.
+        */
+       for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++) {
+               if (pd[i].node_id == 0) {
+                       pd[i].node_id = idx;
+                       break;
+               }
+       }
+
+done:
+       if (!genpd_data->domains[i] || i == ZYNQMP_NUM_DOMAINS)
+               return ERR_PTR(-ENOENT);
+
+       return genpd_data->domains[i];
+}
+
+static int zynqmp_gpd_probe(struct platform_device *pdev)
+{
+       int i;
+       struct genpd_onecell_data *zynqmp_pd_data;
+       struct generic_pm_domain **domains;
+       struct zynqmp_pm_domain *pd;
+       struct device *dev = &pdev->dev;
+
+       pd = devm_kcalloc(dev, ZYNQMP_NUM_DOMAINS, sizeof(*pd), GFP_KERNEL);
+       if (!pd)
+               return -ENOMEM;
+
+       zynqmp_pd_data = devm_kzalloc(dev, sizeof(*zynqmp_pd_data), GFP_KERNEL);
+       if (!zynqmp_pd_data)
+               return -ENOMEM;
+
+       zynqmp_pd_data->xlate = zynqmp_gpd_xlate;
+
+       domains = devm_kcalloc(dev, ZYNQMP_NUM_DOMAINS, sizeof(*domains),
+                              GFP_KERNEL);
+       if (!domains)
+               return -ENOMEM;
+
+       if (!of_device_is_compatible(dev->parent->of_node,
+                                    "xlnx,zynqmp-firmware"))
+               min_capability = ZYNQMP_PM_CAPABILITY_UNUSABLE;
+
+       for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++, pd++) {
+               pd->node_id = 0;
+               pd->gpd.name = kasprintf(GFP_KERNEL, "domain%d", i);
+               pd->gpd.power_off = zynqmp_gpd_power_off;
+               pd->gpd.power_on = zynqmp_gpd_power_on;
+               pd->gpd.attach_dev = zynqmp_gpd_attach_dev;
+               pd->gpd.detach_dev = zynqmp_gpd_detach_dev;
+
+               domains[i] = &pd->gpd;
+
+               /* Mark all PM domains as initially powered off */
+               pm_genpd_init(&pd->gpd, NULL, true);
+       }
+
+       zynqmp_pd_data->domains = domains;
+       zynqmp_pd_data->num_domains = ZYNQMP_NUM_DOMAINS;
+       of_genpd_add_provider_onecell(dev->parent->of_node, zynqmp_pd_data);
+
+       return 0;
+}
+
+static int zynqmp_gpd_remove(struct platform_device *pdev)
+{
+       of_genpd_del_provider(pdev->dev.parent->of_node);
+
+       return 0;
+}
+
+static void zynqmp_gpd_sync_state(struct device *dev)
+{
+       int ret;
+
+       ret = zynqmp_pm_init_finalize();
+       if (ret)
+               dev_warn(dev, "failed to release power management to firmware\n");
+}
+
+static struct platform_driver zynqmp_power_domain_driver = {
+       .driver = {
+               .name = "zynqmp_power_controller",
+               .sync_state = zynqmp_gpd_sync_state,
+       },
+       .probe = zynqmp_gpd_probe,
+       .remove = zynqmp_gpd_remove,
+};
+module_platform_driver(zynqmp_power_domain_driver);
+
+MODULE_ALIAS("platform:zynqmp_power_controller");
index 5ad5f3b3a6b5d8fc91f1ea2e689a65fc087740be..d4926833655327d6a3494a5b6865087df80ad36d 100644 (file)
@@ -197,7 +197,7 @@ int regulator_set_voltage_sel_pickable_regmap(struct regulator_dev *rdev,
        sel += rdev->desc->linear_ranges[i].min_sel;
 
        range = rdev->desc->linear_range_selectors_bitfield[i];
-       range <<= ffs(rdev->desc->vsel_mask) - 1;
+       range <<= ffs(rdev->desc->vsel_range_mask) - 1;
 
        if (rdev->desc->vsel_reg == rdev->desc->vsel_range_reg) {
                ret = regmap_update_bits(rdev->regmap,
index 9ab8555180a3a0bd159b621a57c99bcb8f0413ae..8e14cea15f980829e99afa2c43bf6872fcfd965c 100644 (file)
@@ -724,6 +724,10 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
                return -EEXIST;
        }
 
+       err = -EINVAL;
+       if (!sk_is_tcp(sock->sk))
+               goto free_socket;
+
        err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
        if (err)
                goto free_socket;
index 7f9b221e7c34ae25e663ef30d98075f4f1e83446..ea9b42225e629dd5840e29c8bce622aef7736444 100644 (file)
@@ -6073,7 +6073,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
                                            phba->hba_debugfs_root,
                                            phba,
                                            &lpfc_debugfs_op_multixripools);
-               if (!phba->debug_multixri_pools) {
+               if (IS_ERR(phba->debug_multixri_pools)) {
                        lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
                                         "0527 Cannot create debugfs multixripools\n");
                        goto debug_failed;
@@ -6085,7 +6085,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
                        debugfs_create_file(name, S_IFREG | 0644,
                                            phba->hba_debugfs_root,
                                            phba, &lpfc_cgn_buffer_op);
-               if (!phba->debug_cgn_buffer) {
+               if (IS_ERR(phba->debug_cgn_buffer)) {
                        lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
                                         "6527 Cannot create debugfs "
                                         "cgn_buffer\n");
@@ -6098,7 +6098,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
                        debugfs_create_file(name, S_IFREG | 0644,
                                            phba->hba_debugfs_root,
                                            phba, &lpfc_rx_monitor_op);
-               if (!phba->debug_rx_monitor) {
+               if (IS_ERR(phba->debug_rx_monitor)) {
                        lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
                                         "6528 Cannot create debugfs "
                                         "rx_monitor\n");
@@ -6111,7 +6111,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
                        debugfs_create_file(name, 0644,
                                            phba->hba_debugfs_root,
                                            phba, &lpfc_debugfs_ras_log);
-               if (!phba->debug_ras_log) {
+               if (IS_ERR(phba->debug_ras_log)) {
                        lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
                                         "6148 Cannot create debugfs"
                                         " ras_log\n");
@@ -6132,7 +6132,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
                        debugfs_create_file(name, S_IFREG | 0644,
                                            phba->hba_debugfs_root,
                                            phba, &lpfc_debugfs_op_lockstat);
-               if (!phba->debug_lockstat) {
+               if (IS_ERR(phba->debug_lockstat)) {
                        lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
                                         "4610 Can't create debugfs lockstat\n");
                        goto debug_failed;
@@ -6358,7 +6358,7 @@ nvmeio_off:
                debugfs_create_file(name, 0644,
                                    vport->vport_debugfs_root,
                                    vport, &lpfc_debugfs_op_scsistat);
-       if (!vport->debug_scsistat) {
+       if (IS_ERR(vport->debug_scsistat)) {
                lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
                                 "4611 Cannot create debugfs scsistat\n");
                goto debug_failed;
@@ -6369,7 +6369,7 @@ nvmeio_off:
                debugfs_create_file(name, 0644,
                                    vport->vport_debugfs_root,
                                    vport, &lpfc_debugfs_op_ioktime);
-       if (!vport->debug_ioktime) {
+       if (IS_ERR(vport->debug_ioktime)) {
                lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
                                 "0815 Cannot create debugfs ioktime\n");
                goto debug_failed;
index 51afb60859ebf957c6f4eb1e0f2a169e093e55f3..5154eeaee0ec325c8f293ee52e291ea5d9b7aa2f 100644 (file)
@@ -199,11 +199,12 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
                /* Only 1 thread can drop the initial node reference.  If
                 * another thread has set NLP_DROPPED, this thread is done.
                 */
-               if (!(ndlp->nlp_flag & NLP_DROPPED)) {
+               if (!(ndlp->fc4_xpt_flags & NVME_XPT_REGD) &&
+                   !(ndlp->nlp_flag & NLP_DROPPED)) {
                        ndlp->nlp_flag |= NLP_DROPPED;
                        spin_unlock_irqrestore(&ndlp->lock, iflags);
                        lpfc_nlp_put(ndlp);
-                       spin_lock_irqsave(&ndlp->lock, iflags);
+                       return;
                }
 
                spin_unlock_irqrestore(&ndlp->lock, iflags);
index 39acbcb7ec66a12e246ed3f92699fa5afe430c7e..96e11a26c297eb3949fbdd8d51932c2e703b09fe 100644 (file)
@@ -228,8 +228,7 @@ lpfc_nvme_remoteport_delete(struct nvme_fc_remote_port *remoteport)
        spin_unlock_irq(&ndlp->lock);
 
        /* On a devloss timeout event, one more put is executed provided the
-        * NVME and SCSI rport unregister requests are complete.  If the vport
-        * is unloading, this extra put is executed by lpfc_drop_node.
+        * NVME and SCSI rport unregister requests are complete.
         */
        if (!(ndlp->fc4_xpt_flags & fc4_xpt_flags))
                lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM);
@@ -2567,11 +2566,7 @@ lpfc_nvme_rescan_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
  * nvme_transport perspective.  Loss of an rport just means IO cannot
  * be sent and recovery is completely up to the initator.
  * For now, the driver just unbinds the DID and port_role so that
- * no further IO can be issued.  Changes are planned for later.
- *
- * Notes - the ndlp reference count is not decremented here since
- * since there is no nvme_transport api for devloss.  Node ref count
- * is only adjusted in driver unload.
+ * no further IO can be issued.
  */
 void
 lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
@@ -2646,6 +2641,21 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
                                         "6167 NVME unregister failed %d "
                                         "port_state x%x\n",
                                         ret, remoteport->port_state);
+
+                       if (vport->load_flag & FC_UNLOADING) {
+                               /* Only 1 thread can drop the initial node
+                                * reference. Check if another thread has set
+                                * NLP_DROPPED.
+                                */
+                               spin_lock_irq(&ndlp->lock);
+                               if (!(ndlp->nlp_flag & NLP_DROPPED)) {
+                                       ndlp->nlp_flag |= NLP_DROPPED;
+                                       spin_unlock_irq(&ndlp->lock);
+                                       lpfc_nlp_put(ndlp);
+                                       return;
+                               }
+                               spin_unlock_irq(&ndlp->lock);
+                       }
                }
        }
        return;
index 3554f6b07727324ac5a8259be01bd4ecb8db6565..94abba57582d54ff0394029855f86b47d0861c2a 100644 (file)
@@ -2332,7 +2332,7 @@ struct megasas_instance {
        u32 support_morethan256jbod; /* FW support for more than 256 PD/JBOD */
        bool use_seqnum_jbod_fp;   /* Added for PD sequence */
        bool smp_affinity_enable;
-       spinlock_t crashdump_lock;
+       struct mutex crashdump_lock;
 
        struct megasas_register_set __iomem *reg_set;
        u32 __iomem *reply_post_host_index_addr[MR_MAX_MSIX_REG_ARRAY];
index b9d46dcb521094fa9afc66aa09f7f9e8e73a7b4a..e1aa667dae662dc8b83d6eb928e71b7a248c8cfb 100644 (file)
@@ -3271,14 +3271,13 @@ fw_crash_buffer_store(struct device *cdev,
        struct megasas_instance *instance =
                (struct megasas_instance *) shost->hostdata;
        int val = 0;
-       unsigned long flags;
 
        if (kstrtoint(buf, 0, &val) != 0)
                return -EINVAL;
 
-       spin_lock_irqsave(&instance->crashdump_lock, flags);
+       mutex_lock(&instance->crashdump_lock);
        instance->fw_crash_buffer_offset = val;
-       spin_unlock_irqrestore(&instance->crashdump_lock, flags);
+       mutex_unlock(&instance->crashdump_lock);
        return strlen(buf);
 }
 
@@ -3293,24 +3292,23 @@ fw_crash_buffer_show(struct device *cdev,
        unsigned long dmachunk = CRASH_DMA_BUF_SIZE;
        unsigned long chunk_left_bytes;
        unsigned long src_addr;
-       unsigned long flags;
        u32 buff_offset;
 
-       spin_lock_irqsave(&instance->crashdump_lock, flags);
+       mutex_lock(&instance->crashdump_lock);
        buff_offset = instance->fw_crash_buffer_offset;
        if (!instance->crash_dump_buf ||
                !((instance->fw_crash_state == AVAILABLE) ||
                (instance->fw_crash_state == COPYING))) {
                dev_err(&instance->pdev->dev,
                        "Firmware crash dump is not available\n");
-               spin_unlock_irqrestore(&instance->crashdump_lock, flags);
+               mutex_unlock(&instance->crashdump_lock);
                return -EINVAL;
        }
 
        if (buff_offset > (instance->fw_crash_buffer_size * dmachunk)) {
                dev_err(&instance->pdev->dev,
                        "Firmware crash dump offset is out of range\n");
-               spin_unlock_irqrestore(&instance->crashdump_lock, flags);
+               mutex_unlock(&instance->crashdump_lock);
                return 0;
        }
 
@@ -3322,7 +3320,7 @@ fw_crash_buffer_show(struct device *cdev,
        src_addr = (unsigned long)instance->crash_buf[buff_offset / dmachunk] +
                (buff_offset % dmachunk);
        memcpy(buf, (void *)src_addr, size);
-       spin_unlock_irqrestore(&instance->crashdump_lock, flags);
+       mutex_unlock(&instance->crashdump_lock);
 
        return size;
 }
@@ -3347,7 +3345,6 @@ fw_crash_state_store(struct device *cdev,
        struct megasas_instance *instance =
                (struct megasas_instance *) shost->hostdata;
        int val = 0;
-       unsigned long flags;
 
        if (kstrtoint(buf, 0, &val) != 0)
                return -EINVAL;
@@ -3361,9 +3358,9 @@ fw_crash_state_store(struct device *cdev,
        instance->fw_crash_state = val;
 
        if ((val == COPIED) || (val == COPY_ERROR)) {
-               spin_lock_irqsave(&instance->crashdump_lock, flags);
+               mutex_lock(&instance->crashdump_lock);
                megasas_free_host_crash_buffer(instance);
-               spin_unlock_irqrestore(&instance->crashdump_lock, flags);
+               mutex_unlock(&instance->crashdump_lock);
                if (val == COPY_ERROR)
                        dev_info(&instance->pdev->dev, "application failed to "
                                "copy Firmware crash dump\n");
@@ -7422,7 +7419,7 @@ static inline void megasas_init_ctrl_params(struct megasas_instance *instance)
        init_waitqueue_head(&instance->int_cmd_wait_q);
        init_waitqueue_head(&instance->abort_cmd_wait_q);
 
-       spin_lock_init(&instance->crashdump_lock);
+       mutex_init(&instance->crashdump_lock);
        spin_lock_init(&instance->mfi_pool_lock);
        spin_lock_init(&instance->hba_lock);
        spin_lock_init(&instance->stream_lock);
index 33053db5a7134c4ed230ed8fb901956e5a96ab30..90069c7b164256bb98ee745e8a8da8244ae05ef1 100644 (file)
@@ -4180,7 +4180,7 @@ pm8001_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
        payload.sas_identify.dev_type = SAS_END_DEVICE;
        payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
        memcpy(payload.sas_identify.sas_addr,
-               pm8001_ha->sas_addr, SAS_ADDR_SIZE);
+               &pm8001_ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE);
        payload.sas_identify.phy_id = phy_id;
 
        return pm8001_mpi_build_cmd(pm8001_ha, 0, opcode, &payload,
index 5e5ce1e74c3b0567d411b79d7fd30d5ae222e3c9..443a3176c6c0c9911658e7d7453f976b7a66a0d9 100644 (file)
@@ -273,7 +273,6 @@ static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id)
        return ret;
 }
 
-static u32 pm8001_setup_irq(struct pm8001_hba_info *pm8001_ha);
 static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha);
 
 /**
@@ -294,13 +293,6 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
        pm8001_dbg(pm8001_ha, INIT, "pm8001_alloc: PHY:%x\n",
                   pm8001_ha->chip->n_phy);
 
-       /* Setup Interrupt */
-       rc = pm8001_setup_irq(pm8001_ha);
-       if (rc) {
-               pm8001_dbg(pm8001_ha, FAIL,
-                          "pm8001_setup_irq failed [ret: %d]\n", rc);
-               goto err_out;
-       }
        /* Request Interrupt */
        rc = pm8001_request_irq(pm8001_ha);
        if (rc)
@@ -1031,47 +1023,38 @@ static u32 pm8001_request_msix(struct pm8001_hba_info *pm8001_ha)
 }
 #endif
 
-static u32 pm8001_setup_irq(struct pm8001_hba_info *pm8001_ha)
-{
-       struct pci_dev *pdev;
-
-       pdev = pm8001_ha->pdev;
-
-#ifdef PM8001_USE_MSIX
-       if (pci_find_capability(pdev, PCI_CAP_ID_MSIX))
-               return pm8001_setup_msix(pm8001_ha);
-       pm8001_dbg(pm8001_ha, INIT, "MSIX not supported!!!\n");
-#endif
-       return 0;
-}
-
 /**
  * pm8001_request_irq - register interrupt
  * @pm8001_ha: our ha struct.
  */
 static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha)
 {
-       struct pci_dev *pdev;
+       struct pci_dev *pdev = pm8001_ha->pdev;
+#ifdef PM8001_USE_MSIX
        int rc;
 
-       pdev = pm8001_ha->pdev;
+       if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) {
+               rc = pm8001_setup_msix(pm8001_ha);
+               if (rc) {
+                       pm8001_dbg(pm8001_ha, FAIL,
+                                  "pm8001_setup_irq failed [ret: %d]\n", rc);
+                       return rc;
+               }
 
-#ifdef PM8001_USE_MSIX
-       if (pdev->msix_cap && pci_msi_enabled())
-               return pm8001_request_msix(pm8001_ha);
-       else {
-               pm8001_dbg(pm8001_ha, INIT, "MSIX not supported!!!\n");
-               goto intx;
+               if (pdev->msix_cap && pci_msi_enabled())
+                       return pm8001_request_msix(pm8001_ha);
        }
+
+       pm8001_dbg(pm8001_ha, INIT, "MSIX not supported!!!\n");
 #endif
 
-intx:
        /* initialize the INT-X interrupt */
        pm8001_ha->irq_vector[0].irq_id = 0;
        pm8001_ha->irq_vector[0].drv_inst = pm8001_ha;
-       rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED,
-               pm8001_ha->name, SHOST_TO_SAS_HA(pm8001_ha->shost));
-       return rc;
+
+       return request_irq(pdev->irq, pm8001_interrupt_handler_intx,
+                          IRQF_SHARED, pm8001_ha->name,
+                          SHOST_TO_SAS_HA(pm8001_ha->shost));
 }
 
 /**
index f6857632dc7cd70d6cb3682fb43603b40d798632..3afd9443c4254afd5507f26683996978fda80ac0 100644 (file)
@@ -3671,10 +3671,12 @@ static int mpi_set_controller_config_resp(struct pm8001_hba_info *pm8001_ha,
                        (struct set_ctrl_cfg_resp *)(piomb + 4);
        u32 status = le32_to_cpu(pPayload->status);
        u32 err_qlfr_pgcd = le32_to_cpu(pPayload->err_qlfr_pgcd);
+       u32 tag = le32_to_cpu(pPayload->tag);
 
        pm8001_dbg(pm8001_ha, MSG,
                   "SET CONTROLLER RESP: status 0x%x qlfr_pgcd 0x%x\n",
                   status, err_qlfr_pgcd);
+       pm8001_tag_free(pm8001_ha, tag);
 
        return 0;
 }
@@ -4671,7 +4673,7 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
        payload.sas_identify.dev_type = SAS_END_DEVICE;
        payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
        memcpy(payload.sas_identify.sas_addr,
-         &pm8001_ha->sas_addr, SAS_ADDR_SIZE);
+               &pm8001_ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE);
        payload.sas_identify.phy_id = phy_id;
 
        return pm8001_mpi_build_cmd(pm8001_ha, 0, opcode, &payload,
index 19f0b93fa3d85a283bcfb77125def4d38845e3cd..d592ee9170c11f373971028a804f44a6ba6042b7 100644 (file)
@@ -307,9 +307,9 @@ static int ppa_out(ppa_struct *dev, char *buffer, int len)
        case PPA_EPP_8:
                epp_reset(ppb);
                w_ctr(ppb, 0x4);
-               if (dev->mode == PPA_EPP_32 && !(((long) buffer | len) & 0x01))
+               if (dev->mode == PPA_EPP_32 && !(((long) buffer | len) & 0x03))
                        outsl(ppb + 4, buffer, len >> 2);
-               else if (dev->mode == PPA_EPP_16 && !(((long) buffer | len) & 0x03))
+               else if (dev->mode == PPA_EPP_16 && !(((long) buffer | len) & 0x01))
                        outsw(ppb + 4, buffer, len >> 1);
                else
                        outsb(ppb + 4, buffer, len);
index 4750ec5789a80db9f07060599d3705ddc6bcc062..10fe3383855c00558e0ffc26268023001376f796 100644 (file)
@@ -1904,6 +1904,7 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts)
                goto drop_rdata_kref;
        }
 
+       spin_lock_irqsave(&fcport->rport_lock, flags);
        if (!test_bit(QEDF_CMD_OUTSTANDING, &io_req->flags) ||
            test_bit(QEDF_CMD_IN_CLEANUP, &io_req->flags) ||
            test_bit(QEDF_CMD_IN_ABORT, &io_req->flags)) {
@@ -1911,17 +1912,20 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts)
                         "io_req xid=0x%x sc_cmd=%p already in cleanup or abort processing or already completed.\n",
                         io_req->xid, io_req->sc_cmd);
                rc = 1;
+               spin_unlock_irqrestore(&fcport->rport_lock, flags);
                goto drop_rdata_kref;
        }
 
+       /* Set the command type to abort */
+       io_req->cmd_type = QEDF_ABTS;
+       spin_unlock_irqrestore(&fcport->rport_lock, flags);
+
        kref_get(&io_req->refcount);
 
        xid = io_req->xid;
        qedf->control_requests++;
        qedf->packet_aborts++;
 
-       /* Set the command type to abort */
-       io_req->cmd_type = QEDF_ABTS;
        io_req->return_scsi_cmd_on_abts = return_scsi_cmd_on_abts;
 
        set_bit(QEDF_CMD_IN_ABORT, &io_req->flags);
@@ -2210,7 +2214,9 @@ process_els:
                  refcount, fcport, fcport->rdata->ids.port_id);
 
        /* Cleanup cmds re-use the same TID as the original I/O */
+       spin_lock_irqsave(&fcport->rport_lock, flags);
        io_req->cmd_type = QEDF_CLEANUP;
+       spin_unlock_irqrestore(&fcport->rport_lock, flags);
        io_req->return_scsi_cmd_on_abts = return_scsi_cmd_on_abts;
 
        init_completion(&io_req->cleanup_done);
index 7825765c936cd651b276af2507799664b5cedeb1..91f3f1d7098eb5b4b0680fb127ebc1978ec08f53 100644 (file)
@@ -2805,6 +2805,8 @@ void qedf_process_cqe(struct qedf_ctx *qedf, struct fcoe_cqe *cqe)
        struct qedf_ioreq *io_req;
        struct qedf_rport *fcport;
        u32 comp_type;
+       u8 io_comp_type;
+       unsigned long flags;
 
        comp_type = (cqe->cqe_data >> FCOE_CQE_CQE_TYPE_SHIFT) &
            FCOE_CQE_CQE_TYPE_MASK;
@@ -2838,11 +2840,14 @@ void qedf_process_cqe(struct qedf_ctx *qedf, struct fcoe_cqe *cqe)
                return;
        }
 
+       spin_lock_irqsave(&fcport->rport_lock, flags);
+       io_comp_type = io_req->cmd_type;
+       spin_unlock_irqrestore(&fcport->rport_lock, flags);
 
        switch (comp_type) {
        case FCOE_GOOD_COMPLETION_CQE_TYPE:
                atomic_inc(&fcport->free_sqes);
-               switch (io_req->cmd_type) {
+               switch (io_comp_type) {
                case QEDF_SCSI_CMD:
                        qedf_scsi_completion(qedf, cqe, io_req);
                        break;
index f060e593685de0266d93950d3e263202b263cdde..a7a364760b8002bd9b4bb02270d5e83fe4c5b3f0 100644 (file)
@@ -116,7 +116,7 @@ qla2x00_dfs_create_rport(scsi_qla_host_t *vha, struct fc_port *fp)
 
        sprintf(wwn, "pn-%016llx", wwn_to_u64(fp->port_name));
        fp->dfs_rport_dir = debugfs_create_dir(wwn, vha->dfs_rport_root);
-       if (!fp->dfs_rport_dir)
+       if (IS_ERR(fp->dfs_rport_dir))
                return;
        if (NVME_TARGET(vha->hw, fp))
                debugfs_create_file("dev_loss_tmo", 0600, fp->dfs_rport_dir,
@@ -708,14 +708,14 @@ create_nodes:
        if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) {
                ha->tgt.dfs_naqp = debugfs_create_file("naqp",
                    0400, ha->dfs_dir, vha, &dfs_naqp_ops);
-               if (!ha->tgt.dfs_naqp) {
+               if (IS_ERR(ha->tgt.dfs_naqp)) {
                        ql_log(ql_log_warn, vha, 0xd011,
                               "Unable to create debugFS naqp node.\n");
                        goto out;
                }
        }
        vha->dfs_rport_root = debugfs_create_dir("rports", ha->dfs_dir);
-       if (!vha->dfs_rport_root) {
+       if (IS_ERR(vha->dfs_rport_root)) {
                ql_log(ql_log_warn, vha, 0xd012,
                       "Unable to create debugFS rports node.\n");
                goto out;
index 0556969f6dc1bb5e65a92a6bd189afe733f49498..a4a56ab0ba7473f9c6258ed56e8d8bf03ca9aa7a 100644 (file)
@@ -577,7 +577,7 @@ fcport_is_bigger(fc_port_t *fcport)
 static inline struct qla_qpair *
 qla_mapq_nvme_select_qpair(struct qla_hw_data *ha, struct qla_qpair *qpair)
 {
-       int cpuid = smp_processor_id();
+       int cpuid = raw_smp_processor_id();
 
        if (qpair->cpuid != cpuid &&
            ha->qp_cpu_map[cpuid]) {
index e987881918978a66bb05fe32fa53d561554fbeff..d48007e182881b1fcc3aada1327fe77e600d3e2b 100644 (file)
@@ -3965,7 +3965,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
        if (!ha->flags.fw_started)
                return;
 
-       if (rsp->qpair->cpuid != smp_processor_id() || !rsp->qpair->rcv_intr) {
+       if (rsp->qpair->cpuid != raw_smp_processor_id() || !rsp->qpair->rcv_intr) {
                rsp->qpair->rcv_intr = 1;
 
                if (!rsp->qpair->cpu_mapped)
@@ -4468,7 +4468,7 @@ qla2xxx_msix_rsp_q(int irq, void *dev_id)
        }
        ha = qpair->hw;
 
-       queue_work_on(smp_processor_id(), ha->wq, &qpair->q_work);
+       queue_work(ha->wq, &qpair->q_work);
 
        return IRQ_HANDLED;
 }
@@ -4494,7 +4494,7 @@ qla2xxx_msix_rsp_q_hs(int irq, void *dev_id)
        wrt_reg_dword(&reg->hccr, HCCRX_CLR_RISC_INT);
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-       queue_work_on(smp_processor_id(), ha->wq, &qpair->q_work);
+       queue_work(ha->wq, &qpair->q_work);
 
        return IRQ_HANDLED;
 }
index db753d71299109dcb0b8601f50ba9093fca03e32..a8ddf356e6626038fcaf17df560259bad772fec3 100644 (file)
@@ -399,14 +399,14 @@ static int qla_nvme_xmt_ls_rsp(struct nvme_fc_local_port *lport,
        nvme->u.nvme.dl = 0;
        nvme->u.nvme.timeout_sec = 0;
        nvme->u.nvme.cmd_dma = fd_resp->rspdma;
-       nvme->u.nvme.cmd_len = fd_resp->rsplen;
+       nvme->u.nvme.cmd_len = cpu_to_le32(fd_resp->rsplen);
        nvme->u.nvme.rsp_len = 0;
        nvme->u.nvme.rsp_dma = 0;
        nvme->u.nvme.exchange_address = uctx->exchange_address;
        nvme->u.nvme.nport_handle = uctx->nport_handle;
        nvme->u.nvme.ox_id = uctx->ox_id;
        dma_sync_single_for_device(&ha->pdev->dev, nvme->u.nvme.cmd_dma,
-                                  le32_to_cpu(fd_resp->rsplen), DMA_TO_DEVICE);
+                                  fd_resp->rsplen, DMA_TO_DEVICE);
 
        ql_dbg(ql_dbg_unsol, vha, 0x2122,
               "Unsol lsreq portid=%06x %8phC exchange_address 0x%x ox_id 0x%x hdl 0x%x\n",
@@ -504,13 +504,13 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport,
        nvme->u.nvme.desc = fd;
        nvme->u.nvme.dir = 0;
        nvme->u.nvme.dl = 0;
-       nvme->u.nvme.cmd_len = fd->rqstlen;
-       nvme->u.nvme.rsp_len = fd->rsplen;
+       nvme->u.nvme.cmd_len = cpu_to_le32(fd->rqstlen);
+       nvme->u.nvme.rsp_len = cpu_to_le32(fd->rsplen);
        nvme->u.nvme.rsp_dma = fd->rspdma;
        nvme->u.nvme.timeout_sec = fd->timeout;
        nvme->u.nvme.cmd_dma = fd->rqstdma;
        dma_sync_single_for_device(&ha->pdev->dev, nvme->u.nvme.cmd_dma,
-           le32_to_cpu(fd->rqstlen), DMA_TO_DEVICE);
+           fd->rqstlen, DMA_TO_DEVICE);
 
        rval = qla2x00_start_sp(sp);
        if (rval != QLA_SUCCESS) {
index 2b815a9928ea3db0ecaa35172649d88b1e86bea6..2ef2dbac0db2739d82c590f4afd987e893230931 100644 (file)
@@ -4425,8 +4425,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
                queue_work_on(cmd->se_cmd.cpuid, qla_tgt_wq, &cmd->work);
        } else if (ha->msix_count) {
                if (cmd->atio.u.isp24.fcp_cmnd.rddata)
-                       queue_work_on(smp_processor_id(), qla_tgt_wq,
-                           &cmd->work);
+                       queue_work(qla_tgt_wq, &cmd->work);
                else
                        queue_work_on(cmd->se_cmd.cpuid, qla_tgt_wq,
                            &cmd->work);
index 3b5ba4b47b3b2717708b64f6e85fec986513070a..68a0e6a2fb6e98fa60a68c81e56fa87e4a1c1bcb 100644 (file)
@@ -310,7 +310,7 @@ static void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *cmd)
        cmd->trc_flags |= TRC_CMD_DONE;
 
        INIT_WORK(&cmd->work, tcm_qla2xxx_complete_free);
-       queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work);
+       queue_work(tcm_qla2xxx_free_wq, &cmd->work);
 }
 
 /*
@@ -547,7 +547,7 @@ static void tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd)
        cmd->trc_flags |= TRC_DATA_IN;
        cmd->cmd_in_wq = 1;
        INIT_WORK(&cmd->work, tcm_qla2xxx_handle_data_work);
-       queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work);
+       queue_work(tcm_qla2xxx_free_wq, &cmd->work);
 }
 
 static int tcm_qla2xxx_chk_dif_tags(uint32_t tag)
index a8a74c7cb79f85baf691df3bc7994030ed4c17f5..498e35c8db2c1d733cc33a197e5cb04d06fd6c43 100644 (file)
@@ -662,7 +662,7 @@ static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx,
                if (spi_imx->count >= 512)
                        ctrl |= 0xFFF << MX51_ECSPI_CTRL_BL_OFFSET;
                else
-                       ctrl |= (spi_imx->count*8 - 1)
+                       ctrl |= (spi_imx->count * spi_imx->bits_per_word - 1)
                                << MX51_ECSPI_CTRL_BL_OFFSET;
        }
 
index a7381e774b95391b7780a2181a82ca35a73c773c..57d767a68e7b2766dcea5510809cf2f09e0bef63 100644 (file)
@@ -72,6 +72,7 @@ static const struct pci_device_id intel_spi_pci_ids[] = {
        { PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info },
        { PCI_VDEVICE(INTEL, 0x51a4), (unsigned long)&cnl_info },
        { PCI_VDEVICE(INTEL, 0x54a4), (unsigned long)&cnl_info },
+       { PCI_VDEVICE(INTEL, 0x5794), (unsigned long)&cnl_info },
        { PCI_VDEVICE(INTEL, 0x7a24), (unsigned long)&cnl_info },
        { PCI_VDEVICE(INTEL, 0x7aa4), (unsigned long)&cnl_info },
        { PCI_VDEVICE(INTEL, 0x7e23), (unsigned long)&cnl_info },
index 45a4acc956610a911674f811e2d7bf53492fd7a2..c964f41dcc428c100c1b3e4c56912e0eed379f7a 100644 (file)
@@ -1084,6 +1084,13 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f)
        fspi_writel(f, FSPI_AHBCR_PREF_EN | FSPI_AHBCR_RDADDROPT,
                 base + FSPI_AHBCR);
 
+       /* Reset the FLSHxCR1 registers. */
+       reg = FSPI_FLSHXCR1_TCSH(0x3) | FSPI_FLSHXCR1_TCSS(0x3);
+       fspi_writel(f, reg, base + FSPI_FLSHA1CR1);
+       fspi_writel(f, reg, base + FSPI_FLSHA2CR1);
+       fspi_writel(f, reg, base + FSPI_FLSHB1CR1);
+       fspi_writel(f, reg, base + FSPI_FLSHB2CR1);
+
        /* AHB Read - Set lut sequence ID for all CS. */
        fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA1CR2);
        fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA2CR2);
index b6d66caba4c02eb3e988ad9a5f76317a4244af32..ef665f470c5b5ed3f24efbc5012e04e764d629ae 100644 (file)
@@ -277,6 +277,7 @@ struct stm32_spi_cfg {
  * @fifo_size: size of the embedded fifo in bytes
  * @cur_midi: master inter-data idleness in ns
  * @cur_speed: speed configured in Hz
+ * @cur_half_period: time of a half bit in us
  * @cur_bpw: number of bits in a single SPI data frame
  * @cur_fthlv: fifo threshold level (data frames in a single data packet)
  * @cur_comm: SPI communication mode
@@ -304,6 +305,7 @@ struct stm32_spi {
 
        unsigned int cur_midi;
        unsigned int cur_speed;
+       unsigned int cur_half_period;
        unsigned int cur_bpw;
        unsigned int cur_fthlv;
        unsigned int cur_comm;
@@ -468,6 +470,8 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz,
 
        spi->cur_speed = spi->clk_rate / (1 << mbrdiv);
 
+       spi->cur_half_period = DIV_ROUND_CLOSEST(USEC_PER_SEC, 2 * spi->cur_speed);
+
        return mbrdiv - 1;
 }
 
@@ -709,6 +713,10 @@ static void stm32h7_spi_disable(struct stm32_spi *spi)
                return;
        }
 
+       /* Add a delay to make sure that transmission is ended. */
+       if (spi->cur_half_period)
+               udelay(spi->cur_half_period);
+
        if (spi->cur_usedma && spi->dma_tx)
                dmaengine_terminate_async(spi->dma_tx);
        if (spi->cur_usedma && spi->dma_rx)
index 94d9a33d9af56e8c76bf7b14937d97bec190a3a9..9a46b2478f4e98bd38c794b17fa7a2bdae4e36f4 100644 (file)
@@ -1340,9 +1340,9 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
        return 0;
 
 clk_dis_all:
-       pm_runtime_put_sync(&pdev->dev);
-       pm_runtime_set_suspended(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
+       pm_runtime_put_noidle(&pdev->dev);
+       pm_runtime_set_suspended(&pdev->dev);
        clk_disable_unprepare(xqspi->refclk);
 clk_dis_pclk:
        clk_disable_unprepare(xqspi->pclk);
@@ -1366,11 +1366,15 @@ static void zynqmp_qspi_remove(struct platform_device *pdev)
 {
        struct zynqmp_qspi *xqspi = platform_get_drvdata(pdev);
 
+       pm_runtime_get_sync(&pdev->dev);
+
        zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, 0x0);
+
+       pm_runtime_disable(&pdev->dev);
+       pm_runtime_put_noidle(&pdev->dev);
+       pm_runtime_set_suspended(&pdev->dev);
        clk_disable_unprepare(xqspi->refclk);
        clk_disable_unprepare(xqspi->pclk);
-       pm_runtime_set_suspended(&pdev->dev);
-       pm_runtime_disable(&pdev->dev);
 }
 
 MODULE_DEVICE_TABLE(of, zynqmp_qspi_of_match);
index 936e5ff1b209ecb9df704766d214326eee5e811d..d5860c1c1f469e5528dc69202e75697b57a794c2 100644 (file)
@@ -1392,16 +1392,16 @@ static ssize_t target_wwn_vendor_id_store(struct config_item *item,
        /* +2 to allow for a trailing (stripped) '\n' and null-terminator */
        unsigned char buf[INQUIRY_VENDOR_LEN + 2];
        char *stripped = NULL;
-       size_t len;
+       ssize_t len;
        ssize_t ret;
 
-       len = strlcpy(buf, page, sizeof(buf));
-       if (len < sizeof(buf)) {
+       len = strscpy(buf, page, sizeof(buf));
+       if (len > 0) {
                /* Strip any newline added from userspace. */
                stripped = strstrip(buf);
                len = strlen(stripped);
        }
-       if (len > INQUIRY_VENDOR_LEN) {
+       if (len < 0 || len > INQUIRY_VENDOR_LEN) {
                pr_err("Emulated T10 Vendor Identification exceeds"
                        " INQUIRY_VENDOR_LEN: " __stringify(INQUIRY_VENDOR_LEN)
                        "\n");
@@ -1448,16 +1448,16 @@ static ssize_t target_wwn_product_id_store(struct config_item *item,
        /* +2 to allow for a trailing (stripped) '\n' and null-terminator */
        unsigned char buf[INQUIRY_MODEL_LEN + 2];
        char *stripped = NULL;
-       size_t len;
+       ssize_t len;
        ssize_t ret;
 
-       len = strlcpy(buf, page, sizeof(buf));
-       if (len < sizeof(buf)) {
+       len = strscpy(buf, page, sizeof(buf));
+       if (len > 0) {
                /* Strip any newline added from userspace. */
                stripped = strstrip(buf);
                len = strlen(stripped);
        }
-       if (len > INQUIRY_MODEL_LEN) {
+       if (len < 0 || len > INQUIRY_MODEL_LEN) {
                pr_err("Emulated T10 Vendor exceeds INQUIRY_MODEL_LEN: "
                         __stringify(INQUIRY_MODEL_LEN)
                        "\n");
@@ -1504,16 +1504,16 @@ static ssize_t target_wwn_revision_store(struct config_item *item,
        /* +2 to allow for a trailing (stripped) '\n' and null-terminator */
        unsigned char buf[INQUIRY_REVISION_LEN + 2];
        char *stripped = NULL;
-       size_t len;
+       ssize_t len;
        ssize_t ret;
 
-       len = strlcpy(buf, page, sizeof(buf));
-       if (len < sizeof(buf)) {
+       len = strscpy(buf, page, sizeof(buf));
+       if (len > 0) {
                /* Strip any newline added from userspace. */
                stripped = strstrip(buf);
                len = strlen(stripped);
        }
-       if (len > INQUIRY_REVISION_LEN) {
+       if (len < 0 || len > INQUIRY_REVISION_LEN) {
                pr_err("Emulated T10 Revision exceeds INQUIRY_REVISION_LEN: "
                         __stringify(INQUIRY_REVISION_LEN)
                        "\n");
index 687adc9e086ca942ba85dd591ab3b7bf76cc9192..0686882bcbda351fbf5c46b6a66cdf4cfe35e9e0 100644 (file)
@@ -264,6 +264,7 @@ void target_free_cmd_counter(struct target_cmd_counter *cmd_cnt)
                percpu_ref_put(&cmd_cnt->refcnt);
 
        percpu_ref_exit(&cmd_cnt->refcnt);
+       kfree(cmd_cnt);
 }
 EXPORT_SYMBOL_GPL(target_free_cmd_counter);
 
index 372d64756ed64b10c3dd9096aa20886320837ff9..3c15f6a9e91c0a2c24dceecea1815b6bd2600068 100644 (file)
@@ -217,12 +217,12 @@ unlock:
        return rc;
 }
 
+/* mutex must be held by caller */
 static void destroy_session(struct kref *ref)
 {
        struct amdtee_session *sess = container_of(ref, struct amdtee_session,
                                                   refcount);
 
-       mutex_lock(&session_list_mutex);
        list_del(&sess->list_node);
        mutex_unlock(&session_list_mutex);
        kfree(sess);
@@ -272,7 +272,8 @@ int amdtee_open_session(struct tee_context *ctx,
        if (arg->ret != TEEC_SUCCESS) {
                pr_err("open_session failed %d\n", arg->ret);
                handle_unload_ta(ta_handle);
-               kref_put(&sess->refcount, destroy_session);
+               kref_put_mutex(&sess->refcount, destroy_session,
+                              &session_list_mutex);
                goto out;
        }
 
@@ -290,7 +291,8 @@ int amdtee_open_session(struct tee_context *ctx,
                pr_err("reached maximum session count %d\n", TEE_NUM_SESSIONS);
                handle_close_session(ta_handle, session_info);
                handle_unload_ta(ta_handle);
-               kref_put(&sess->refcount, destroy_session);
+               kref_put_mutex(&sess->refcount, destroy_session,
+                              &session_list_mutex);
                rc = -ENOMEM;
                goto out;
        }
@@ -331,7 +333,7 @@ int amdtee_close_session(struct tee_context *ctx, u32 session)
        handle_close_session(ta_handle, session_info);
        handle_unload_ta(ta_handle);
 
-       kref_put(&sess->refcount, destroy_session);
+       kref_put_mutex(&sess->refcount, destroy_session, &session_list_mutex);
 
        return 0;
 }
index 8717a33435125ca33009e79afd89983c1a742dda..58533ea75cd92563a19acd07e37f9095031eb9a7 100644 (file)
@@ -348,12 +348,14 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip_id)
        struct thermal_trip trip;
 
        /* Ignore disabled trip points */
-       if (test_bit(trip_id, &tz->trips_disabled) ||
-           trip.temperature == THERMAL_TEMP_INVALID)
+       if (test_bit(trip_id, &tz->trips_disabled))
                return;
 
        __thermal_zone_get_trip(tz, trip_id, &trip);
 
+       if (trip.temperature == THERMAL_TEMP_INVALID)
+               return;
+
        if (tz->last_temperature != THERMAL_TEMP_INVALID) {
                if (tz->last_temperature < trip.temperature &&
                    tz->temperature >= trip.temperature)
index 4ca905723429c7653e8add3f389602c12b80b439..1e0655b63259fe391f8a43a3a71f01172b5f74b8 100644 (file)
@@ -37,8 +37,10 @@ static int of_find_trip_id(struct device_node *np, struct device_node *trip)
         */
        for_each_child_of_node(trips, t) {
 
-               if (t == trip)
+               if (t == trip) {
+                       of_node_put(t);
                        goto out;
+               }
                i++;
        }
 
@@ -401,8 +403,10 @@ static int thermal_of_for_each_cooling_maps(struct thermal_zone_device *tz,
 
        for_each_child_of_node(cm_np, child) {
                ret = thermal_of_for_each_cooling_device(tz_np, child, tz, cdev, action);
-               if (ret)
+               if (ret) {
+                       of_node_put(child);
                        break;
+               }
        }
 
        of_node_put(cm_np);
index 6c20c9f90a05acb777b13019fa341fcb80e69320..4e6a97db894e9cfd19c0015a755c8638a3d1b3c6 100644 (file)
@@ -185,9 +185,6 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
        if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip_id) != 1)
                return -EINVAL;
 
-       if (kstrtoint(buf, 10, &trip.hysteresis))
-               return -EINVAL;
-
        mutex_lock(&tz->lock);
 
        if (!device_is_registered(dev)) {
@@ -198,7 +195,11 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
        ret = __thermal_zone_get_trip(tz, trip_id, &trip);
        if (ret)
                goto unlock;
-       
+
+       ret = kstrtoint(buf, 10, &trip.hysteresis);
+       if (ret)
+               goto unlock;
+
        ret = thermal_zone_set_trip(tz, trip_id, &trip);
 unlock:
        mutex_unlock(&tz->lock);
index 6ba2613627e135bde426de1fc6148ece29ac9298..0cf0826b805a998abd0d4e2cfa6938de8a46c4f0 100644 (file)
@@ -110,7 +110,8 @@ static inline int __ti_thermal_get_temp(struct thermal_zone_device *tz, int *tem
 }
 
 static int __ti_thermal_get_trend(struct thermal_zone_device *tz,
-                                 struct thermal_trip *trip, enum thermal_trend *trend)
+                                 const struct thermal_trip *trip,
+                                 enum thermal_trend *trend)
 {
        struct ti_thermal_data *data = thermal_zone_device_priv(tz);
        struct ti_bandgap *bgp;
index 93417518c04d15c2403b5742117c909bea8be6e9..c2df07545f966bb566846341bdafabb6ead242ad 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/regulator/consumer.h>
 #include <linux/sched/clock.h>
+#include <linux/iopoll.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_driver.h>
@@ -2299,7 +2300,11 @@ static inline int ufshcd_hba_capabilities(struct ufs_hba *hba)
  */
 static inline bool ufshcd_ready_for_uic_cmd(struct ufs_hba *hba)
 {
-       return ufshcd_readl(hba, REG_CONTROLLER_STATUS) & UIC_COMMAND_READY;
+       u32 val;
+       int ret = read_poll_timeout(ufshcd_readl, val, val & UIC_COMMAND_READY,
+                                   500, UIC_CMD_TIMEOUT * 1000, false, hba,
+                                   REG_CONTROLLER_STATUS);
+       return ret == 0 ? true : false;
 }
 
 /**
@@ -2392,7 +2397,6 @@ __ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd,
                      bool completion)
 {
        lockdep_assert_held(&hba->uic_cmd_mutex);
-       lockdep_assert_held(hba->host->host_lock);
 
        if (!ufshcd_ready_for_uic_cmd(hba)) {
                dev_err(hba->dev,
@@ -2419,7 +2423,6 @@ __ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd,
 int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
 {
        int ret;
-       unsigned long flags;
 
        if (hba->quirks & UFSHCD_QUIRK_BROKEN_UIC_CMD)
                return 0;
@@ -2428,9 +2431,7 @@ int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
        mutex_lock(&hba->uic_cmd_mutex);
        ufshcd_add_delay_before_dme_cmd(hba);
 
-       spin_lock_irqsave(hba->host->host_lock, flags);
        ret = __ufshcd_send_uic_cmd(hba, uic_cmd, true);
-       spin_unlock_irqrestore(hba->host->host_lock, flags);
        if (!ret)
                ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd);
 
@@ -4133,8 +4134,8 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
                wmb();
                reenable_intr = true;
        }
-       ret = __ufshcd_send_uic_cmd(hba, cmd, false);
        spin_unlock_irqrestore(hba->host->host_lock, flags);
+       ret = __ufshcd_send_uic_cmd(hba, cmd, false);
        if (ret) {
                dev_err(hba->dev,
                        "pwr ctrl cmd 0x%x with mode 0x%x uic error %d\n",
index 0c7bf88d4a7fbec2697aabf5e6d3023290d7ffa3..f67733cecfdf5d2b19a1dc8cfb40f78b901bbd11 100644 (file)
@@ -84,6 +84,9 @@ void ucsi_debugfs_register(struct ucsi *ucsi)
 
 void ucsi_debugfs_unregister(struct ucsi *ucsi)
 {
+       if (IS_ERR_OR_NULL(ucsi) || !ucsi->debugfs)
+               return;
+
        debugfs_remove_recursive(ucsi->debugfs->dentry);
        kfree(ucsi->debugfs);
 }
index 1b5a319971ed07f148e54d65de16f267a720252f..30577b1d3de590f123aa6af2c58bae1c6fea08de 100644 (file)
@@ -73,6 +73,7 @@ config DUMMY_CONSOLE_ROWS
 config FRAMEBUFFER_CONSOLE
        bool "Framebuffer Console support"
        depends on FB_CORE && !UML
+       default DRM_FBDEV_EMULATION
        select VT_HW_CONSOLE_BINDING
        select CRC32
        select FONT_SUPPORT
index eac0ba39581e3c5bfc7d6d345aee31a17a7e6730..c29754b65c0ec923387cfb8c1b7e0f47557d33cd 100644 (file)
@@ -1762,7 +1762,7 @@ config FB_COBALT
 
 config FB_SH7760
        bool "SH7760/SH7763/SH7720/SH7721 LCDC support"
-       depends on FB && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763 \
+       depends on FB=y && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763 \
                || CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721)
        select FB_IOMEM_HELPERS
        help
index baf7e852c75b60972ab24ddc10ac773b1a1dbf96..5ac1b063753110d51e5f6b8348e5edf23338e6db 100644 (file)
@@ -28,7 +28,7 @@ config FIRMWARE_EDID
 config FB_DEVICE
        bool "Provide legacy /dev/fb* device"
        depends on FB_CORE
-       default y
+       default FB
        help
          Say Y here if you want the legacy /dev/fb* device file and
          interfaces within sysfs anc procfs. It is only required if you
index c1de8a92e144bd0336c28f3e7b2f6b6b21098571..b2d76c1784bd8a27f004ce20d21cfb754311f6ad 100644 (file)
@@ -551,7 +551,7 @@ static struct i2c_driver ds2482_driver = {
        .driver = {
                .name   = "ds2482",
        },
-       .probe_new      = ds2482_probe,
+       .probe          = ds2482_probe,
        .remove         = ds2482_remove,
        .id_table       = ds2482_id,
 };
index 3bdd5b59661de53300744be47abc5cb6cb6722ee..0bb86e6c4d0aaa78a72960d369e2a56b1feb5137 100644 (file)
@@ -1704,7 +1704,7 @@ void handle_irq_for_port(evtchn_port_t port, struct evtchn_loop_ctrl *ctrl)
        generic_handle_irq(irq);
 }
 
-static int __xen_evtchn_do_upcall(void)
+int xen_evtchn_do_upcall(void)
 {
        struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu);
        int ret = vcpu_info->evtchn_upcall_pending ? IRQ_HANDLED : IRQ_NONE;
@@ -1735,24 +1735,7 @@ static int __xen_evtchn_do_upcall(void)
 
        return ret;
 }
-
-void xen_evtchn_do_upcall(struct pt_regs *regs)
-{
-       struct pt_regs *old_regs = set_irq_regs(regs);
-
-       irq_enter();
-
-       __xen_evtchn_do_upcall();
-
-       irq_exit();
-       set_irq_regs(old_regs);
-}
-
-int xen_hvm_evtchn_do_upcall(void)
-{
-       return __xen_evtchn_do_upcall();
-}
-EXPORT_SYMBOL_GPL(xen_hvm_evtchn_do_upcall);
+EXPORT_SYMBOL_GPL(xen_evtchn_do_upcall);
 
 /* Rebind a new event channel to an existing irq. */
 void rebind_evtchn_irq(evtchn_port_t evtchn, int irq)
index fcc8191315723c6701ec5e7c5b97a73374b899a8..544d3f9010b92aca1e65a5c192b3ff79e6c19816 100644 (file)
@@ -64,7 +64,7 @@ static uint64_t get_callback_via(struct pci_dev *pdev)
 
 static irqreturn_t do_hvm_evtchn_intr(int irq, void *dev_id)
 {
-       return xen_hvm_evtchn_do_upcall();
+       return xen_evtchn_do_upcall();
 }
 
 static int xen_allocate_irq(struct pci_dev *pdev)
index 3282adc84d5215bf6439faca37874a6af22c3096..a25c9910d90b2010531b1a84b3bd2b98268fe9c6 100644 (file)
@@ -31,7 +31,7 @@ config BTRFS_FS
          continue to be mountable and usable by newer kernels.
 
          For more information, please see the web pages at
-         http://btrfs.wiki.kernel.org.
+         https://btrfs.readthedocs.io
 
          To compile this file system support as a module, choose M here. The
          module will be called btrfs.
index 0cb1dee965a02ab8b8866856bd5355053af3b88e..b2e5107b7cecc4021bea90b5a67fd41142415f79 100644 (file)
@@ -3028,8 +3028,16 @@ static int update_block_group_item(struct btrfs_trans_handle *trans,
        btrfs_mark_buffer_dirty(leaf);
 fail:
        btrfs_release_path(path);
-       /* We didn't update the block group item, need to revert @commit_used. */
-       if (ret < 0) {
+       /*
+        * We didn't update the block group item, need to revert commit_used
+        * unless the block group item didn't exist yet - this is to prevent a
+        * race with a concurrent insertion of the block group item, with
+        * insert_block_group_item(), that happened just after we attempted to
+        * update. In that case we would reset commit_used to 0 just after the
+        * insertion set it to a value greater than 0 - if the block group later
+        * becomes with 0 used bytes, we would incorrectly skip its update.
+        */
+       if (ret < 0 && ret != -ENOENT) {
                spin_lock(&cache->lock);
                cache->commit_used = old_commit_used;
                spin_unlock(&cache->lock);
index 53c1211dd60bab23b4574820a1b3a70f2b2c8c15..caf0bbd028d11070ea8d87524c9e8c670e7d905d 100644 (file)
@@ -412,6 +412,7 @@ static void finish_one_item(struct btrfs_delayed_root *delayed_root)
 
 static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item)
 {
+       struct btrfs_delayed_node *delayed_node = delayed_item->delayed_node;
        struct rb_root_cached *root;
        struct btrfs_delayed_root *delayed_root;
 
@@ -419,18 +420,21 @@ static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item)
        if (RB_EMPTY_NODE(&delayed_item->rb_node))
                return;
 
-       delayed_root = delayed_item->delayed_node->root->fs_info->delayed_root;
+       /* If it's in a rbtree, then we need to have delayed node locked. */
+       lockdep_assert_held(&delayed_node->mutex);
+
+       delayed_root = delayed_node->root->fs_info->delayed_root;
 
        BUG_ON(!delayed_root);
 
        if (delayed_item->type == BTRFS_DELAYED_INSERTION_ITEM)
-               root = &delayed_item->delayed_node->ins_root;
+               root = &delayed_node->ins_root;
        else
-               root = &delayed_item->delayed_node->del_root;
+               root = &delayed_node->del_root;
 
        rb_erase_cached(&delayed_item->rb_node, root);
        RB_CLEAR_NODE(&delayed_item->rb_node);
-       delayed_item->delayed_node->count--;
+       delayed_node->count--;
 
        finish_one_item(delayed_root);
 }
@@ -1153,20 +1157,33 @@ static int __btrfs_run_delayed_items(struct btrfs_trans_handle *trans, int nr)
                ret = __btrfs_commit_inode_delayed_items(trans, path,
                                                         curr_node);
                if (ret) {
-                       btrfs_release_delayed_node(curr_node);
-                       curr_node = NULL;
                        btrfs_abort_transaction(trans, ret);
                        break;
                }
 
                prev_node = curr_node;
                curr_node = btrfs_next_delayed_node(curr_node);
+               /*
+                * See the comment below about releasing path before releasing
+                * node. If the commit of delayed items was successful the path
+                * should always be released, but in case of an error, it may
+                * point to locked extent buffers (a leaf at the very least).
+                */
+               ASSERT(path->nodes[0] == NULL);
                btrfs_release_delayed_node(prev_node);
        }
 
+       /*
+        * Release the path to avoid a potential deadlock and lockdep splat when
+        * releasing the delayed node, as that requires taking the delayed node's
+        * mutex. If another task starts running delayed items before we take
+        * the mutex, it will first lock the mutex and then it may try to lock
+        * the same btree path (leaf).
+        */
+       btrfs_free_path(path);
+
        if (curr_node)
                btrfs_release_delayed_node(curr_node);
-       btrfs_free_path(path);
        trans->block_rsv = block_rsv;
 
        return ret;
@@ -1413,7 +1430,29 @@ void btrfs_balance_delayed_items(struct btrfs_fs_info *fs_info)
        btrfs_wq_run_delayed_node(delayed_root, fs_info, BTRFS_DELAYED_BATCH);
 }
 
-/* Will return 0 or -ENOMEM */
+static void btrfs_release_dir_index_item_space(struct btrfs_trans_handle *trans)
+{
+       struct btrfs_fs_info *fs_info = trans->fs_info;
+       const u64 bytes = btrfs_calc_insert_metadata_size(fs_info, 1);
+
+       if (test_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags))
+               return;
+
+       /*
+        * Adding the new dir index item does not require touching another
+        * leaf, so we can release 1 unit of metadata that was previously
+        * reserved when starting the transaction. This applies only to
+        * the case where we had a transaction start and excludes the
+        * transaction join case (when replaying log trees).
+        */
+       trace_btrfs_space_reservation(fs_info, "transaction",
+                                     trans->transid, bytes, 0);
+       btrfs_block_rsv_release(fs_info, trans->block_rsv, bytes, NULL);
+       ASSERT(trans->bytes_reserved >= bytes);
+       trans->bytes_reserved -= bytes;
+}
+
+/* Will return 0, -ENOMEM or -EEXIST (index number collision, unexpected). */
 int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans,
                                   const char *name, int name_len,
                                   struct btrfs_inode *dir,
@@ -1455,6 +1494,27 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans,
 
        mutex_lock(&delayed_node->mutex);
 
+       /*
+        * First attempt to insert the delayed item. This is to make the error
+        * handling path simpler in case we fail (-EEXIST). There's no risk of
+        * any other task coming in and running the delayed item before we do
+        * the metadata space reservation below, because we are holding the
+        * delayed node's mutex and that mutex must also be locked before the
+        * node's delayed items can be run.
+        */
+       ret = __btrfs_add_delayed_item(delayed_node, delayed_item);
+       if (unlikely(ret)) {
+               btrfs_err(trans->fs_info,
+"error adding delayed dir index item, name: %.*s, index: %llu, root: %llu, dir: %llu, dir->index_cnt: %llu, delayed_node->index_cnt: %llu, error: %d",
+                         name_len, name, index, btrfs_root_id(delayed_node->root),
+                         delayed_node->inode_id, dir->index_cnt,
+                         delayed_node->index_cnt, ret);
+               btrfs_release_delayed_item(delayed_item);
+               btrfs_release_dir_index_item_space(trans);
+               mutex_unlock(&delayed_node->mutex);
+               goto release_node;
+       }
+
        if (delayed_node->index_item_leaves == 0 ||
            delayed_node->curr_index_batch_size + data_len > leaf_data_size) {
                delayed_node->curr_index_batch_size = data_len;
@@ -1472,36 +1532,14 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans,
                 * impossible.
                 */
                if (WARN_ON(ret)) {
-                       mutex_unlock(&delayed_node->mutex);
                        btrfs_release_delayed_item(delayed_item);
+                       mutex_unlock(&delayed_node->mutex);
                        goto release_node;
                }
 
                delayed_node->index_item_leaves++;
-       } else if (!test_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags)) {
-               const u64 bytes = btrfs_calc_insert_metadata_size(fs_info, 1);
-
-               /*
-                * Adding the new dir index item does not require touching another
-                * leaf, so we can release 1 unit of metadata that was previously
-                * reserved when starting the transaction. This applies only to
-                * the case where we had a transaction start and excludes the
-                * transaction join case (when replaying log trees).
-                */
-               trace_btrfs_space_reservation(fs_info, "transaction",
-                                             trans->transid, bytes, 0);
-               btrfs_block_rsv_release(fs_info, trans->block_rsv, bytes, NULL);
-               ASSERT(trans->bytes_reserved >= bytes);
-               trans->bytes_reserved -= bytes;
-       }
-
-       ret = __btrfs_add_delayed_item(delayed_node, delayed_item);
-       if (unlikely(ret)) {
-               btrfs_err(trans->fs_info,
-                         "err add delayed dir index item(name: %.*s) into the insertion tree of the delayed node(root id: %llu, inode id: %llu, errno: %d)",
-                         name_len, name, delayed_node->root->root_key.objectid,
-                         delayed_node->inode_id, ret);
-               BUG();
+       } else {
+               btrfs_release_dir_index_item_space(trans);
        }
        mutex_unlock(&delayed_node->mutex);
 
index 0a96ea8c1d3a627fd2950d97187cbd73baf6e0bf..68f60d50e1fd0c2fc1a643cf9d44bdcb5ae36036 100644 (file)
@@ -520,6 +520,7 @@ static bool btree_dirty_folio(struct address_space *mapping,
                struct folio *folio)
 {
        struct btrfs_fs_info *fs_info = btrfs_sb(mapping->host->i_sb);
+       struct btrfs_subpage_info *spi = fs_info->subpage_info;
        struct btrfs_subpage *subpage;
        struct extent_buffer *eb;
        int cur_bit = 0;
@@ -533,18 +534,19 @@ static bool btree_dirty_folio(struct address_space *mapping,
                btrfs_assert_tree_write_locked(eb);
                return filemap_dirty_folio(mapping, folio);
        }
+
+       ASSERT(spi);
        subpage = folio_get_private(folio);
 
-       ASSERT(subpage->dirty_bitmap);
-       while (cur_bit < BTRFS_SUBPAGE_BITMAP_SIZE) {
+       for (cur_bit = spi->dirty_offset;
+            cur_bit < spi->dirty_offset + spi->bitmap_nr_bits;
+            cur_bit++) {
                unsigned long flags;
                u64 cur;
-               u16 tmp = (1 << cur_bit);
 
                spin_lock_irqsave(&subpage->lock, flags);
-               if (!(tmp & subpage->dirty_bitmap)) {
+               if (!test_bit(cur_bit, subpage->bitmaps)) {
                        spin_unlock_irqrestore(&subpage->lock, flags);
-                       cur_bit++;
                        continue;
                }
                spin_unlock_irqrestore(&subpage->lock, flags);
@@ -557,7 +559,7 @@ static bool btree_dirty_folio(struct address_space *mapping,
                btrfs_assert_tree_write_locked(eb);
                free_extent_buffer(eb);
 
-               cur_bit += (fs_info->nodesize >> fs_info->sectorsize_bits);
+               cur_bit += (fs_info->nodesize >> fs_info->sectorsize_bits) - 1;
        }
        return filemap_dirty_folio(mapping, folio);
 }
@@ -1547,7 +1549,7 @@ static int transaction_kthread(void *arg)
 
                delta = ktime_get_seconds() - cur->start_time;
                if (!test_and_clear_bit(BTRFS_FS_COMMIT_TRANS, &fs_info->flags) &&
-                   cur->state < TRANS_STATE_COMMIT_START &&
+                   cur->state < TRANS_STATE_COMMIT_PREP &&
                    delta < fs_info->commit_interval) {
                        spin_unlock(&fs_info->trans_lock);
                        delay -= msecs_to_jiffies((delta - 1) * 1000);
@@ -2682,8 +2684,8 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
        btrfs_lockdep_init_map(fs_info, btrfs_trans_num_extwriters);
        btrfs_lockdep_init_map(fs_info, btrfs_trans_pending_ordered);
        btrfs_lockdep_init_map(fs_info, btrfs_ordered_extent);
-       btrfs_state_lockdep_init_map(fs_info, btrfs_trans_commit_start,
-                                    BTRFS_LOCKDEP_TRANS_COMMIT_START);
+       btrfs_state_lockdep_init_map(fs_info, btrfs_trans_commit_prep,
+                                    BTRFS_LOCKDEP_TRANS_COMMIT_PREP);
        btrfs_state_lockdep_init_map(fs_info, btrfs_trans_unblocked,
                                     BTRFS_LOCKDEP_TRANS_UNBLOCKED);
        btrfs_state_lockdep_init_map(fs_info, btrfs_trans_super_committed,
@@ -4870,7 +4872,7 @@ static int btrfs_cleanup_transaction(struct btrfs_fs_info *fs_info)
        while (!list_empty(&fs_info->trans_list)) {
                t = list_first_entry(&fs_info->trans_list,
                                     struct btrfs_transaction, list);
-               if (t->state >= TRANS_STATE_COMMIT_START) {
+               if (t->state >= TRANS_STATE_COMMIT_PREP) {
                        refcount_inc(&t->use_count);
                        spin_unlock(&fs_info->trans_lock);
                        btrfs_wait_for_commit(fs_info, t->transid);
index ac3fca5a5e4162ddc2769f4e5932370d622ae0b4..6954ae763b86f41bea3a087260a66b1ab6170b8f 100644 (file)
@@ -484,10 +484,8 @@ static void end_bio_extent_writepage(struct btrfs_bio *bbio)
                                   bvec->bv_offset, bvec->bv_len);
 
                btrfs_finish_ordered_extent(bbio->ordered, page, start, len, !error);
-               if (error) {
-                       btrfs_page_clear_uptodate(fs_info, page, start, len);
+               if (error)
                        mapping_set_error(page->mapping, error);
-               }
                btrfs_page_clear_writeback(fs_info, page, start, len);
        }
 
@@ -1456,8 +1454,6 @@ done:
        if (ret) {
                btrfs_mark_ordered_io_finished(BTRFS_I(inode), page, page_start,
                                               PAGE_SIZE, !ret);
-               btrfs_page_clear_uptodate(btrfs_sb(inode->i_sb), page,
-                                         page_start, PAGE_SIZE);
                mapping_set_error(page->mapping, ret);
        }
        unlock_page(page);
@@ -1624,8 +1620,6 @@ static void extent_buffer_write_end_io(struct btrfs_bio *bbio)
                struct page *page = bvec->bv_page;
                u32 len = bvec->bv_len;
 
-               if (!uptodate)
-                       btrfs_page_clear_uptodate(fs_info, page, start, len);
                btrfs_page_clear_writeback(fs_info, page, start, len);
                bio_offset += len;
        }
@@ -2201,7 +2195,6 @@ void extent_write_locked_range(struct inode *inode, struct page *locked_page,
                if (ret) {
                        btrfs_mark_ordered_io_finished(BTRFS_I(inode), page,
                                                       cur, cur_len, !ret);
-                       btrfs_page_clear_uptodate(fs_info, page, cur, cur_len);
                        mapping_set_error(page->mapping, ret);
                }
                btrfs_page_unlock_writer(fs_info, page, cur, cur_len);
index ca46a529d56b1999cff4a785661db40dca049e47..361535c71c0f5a172328832e32b6d00f7b14f131 100644 (file)
@@ -1106,6 +1106,25 @@ void btrfs_check_nocow_unlock(struct btrfs_inode *inode)
        btrfs_drew_write_unlock(&inode->root->snapshot_lock);
 }
 
+static void update_time_for_write(struct inode *inode)
+{
+       struct timespec64 now, ctime;
+
+       if (IS_NOCMTIME(inode))
+               return;
+
+       now = current_time(inode);
+       if (!timespec64_equal(&inode->i_mtime, &now))
+               inode->i_mtime = now;
+
+       ctime = inode_get_ctime(inode);
+       if (!timespec64_equal(&ctime, &now))
+               inode_set_ctime_to_ts(inode, now);
+
+       if (IS_I_VERSION(inode))
+               inode_inc_iversion(inode);
+}
+
 static int btrfs_write_check(struct kiocb *iocb, struct iov_iter *from,
                             size_t count)
 {
@@ -1137,10 +1156,7 @@ static int btrfs_write_check(struct kiocb *iocb, struct iov_iter *from,
         * need to start yet another transaction to update the inode as we will
         * update the inode when we finish writing whatever data we write.
         */
-       if (!IS_NOCMTIME(inode)) {
-               inode->i_mtime = inode_set_ctime_current(inode);
-               inode_inc_iversion(inode);
-       }
+       update_time_for_write(inode);
 
        start_pos = round_down(pos, fs_info->sectorsize);
        oldsize = i_size_read(inode);
@@ -1451,8 +1467,13 @@ static ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from)
        if (iocb->ki_flags & IOCB_NOWAIT)
                ilock_flags |= BTRFS_ILOCK_TRY;
 
-       /* If the write DIO is within EOF, use a shared lock */
-       if (iocb->ki_pos + iov_iter_count(from) <= i_size_read(inode))
+       /*
+        * If the write DIO is within EOF, use a shared lock and also only if
+        * security bits will likely not be dropped by file_remove_privs() called
+        * from btrfs_write_check(). Either will need to be rechecked after the
+        * lock was acquired.
+        */
+       if (iocb->ki_pos + iov_iter_count(from) <= i_size_read(inode) && IS_NOSEC(inode))
                ilock_flags |= BTRFS_ILOCK_SHARED;
 
 relock:
@@ -1460,6 +1481,13 @@ relock:
        if (err < 0)
                return err;
 
+       /* Shared lock cannot be used with security bits set. */
+       if ((ilock_flags & BTRFS_ILOCK_SHARED) && !IS_NOSEC(inode)) {
+               btrfs_inode_unlock(BTRFS_I(inode), ilock_flags);
+               ilock_flags &= ~BTRFS_ILOCK_SHARED;
+               goto relock;
+       }
+
        err = generic_write_checks(iocb, from);
        if (err <= 0) {
                btrfs_inode_unlock(BTRFS_I(inode), ilock_flags);
index f09fbdc43f0f5b15c71d67564cfb264764ff1169..7814b9d654ce1234465bf8ad37a7890e06fd88aa 100644 (file)
@@ -1085,9 +1085,6 @@ static void submit_uncompressed_range(struct btrfs_inode *inode,
                        btrfs_mark_ordered_io_finished(inode, locked_page,
                                                       page_start, PAGE_SIZE,
                                                       !ret);
-                       btrfs_page_clear_uptodate(inode->root->fs_info,
-                                                 locked_page, page_start,
-                                                 PAGE_SIZE);
                        mapping_set_error(locked_page->mapping, ret);
                        unlock_page(locked_page);
                }
@@ -2791,7 +2788,6 @@ out_page:
                mapping_set_error(page->mapping, ret);
                btrfs_mark_ordered_io_finished(inode, page, page_start,
                                               PAGE_SIZE, !ret);
-               btrfs_page_clear_uptodate(fs_info, page, page_start, PAGE_SIZE);
                clear_page_dirty_for_io(page);
        }
        btrfs_page_clear_checked(fs_info, page, page_start, PAGE_SIZE);
@@ -5769,20 +5765,24 @@ out:
 
 static int btrfs_get_dir_last_index(struct btrfs_inode *dir, u64 *index)
 {
-       if (dir->index_cnt == (u64)-1) {
-               int ret;
+       int ret = 0;
 
+       btrfs_inode_lock(dir, 0);
+       if (dir->index_cnt == (u64)-1) {
                ret = btrfs_inode_delayed_dir_index_count(dir);
                if (ret) {
                        ret = btrfs_set_inode_index_count(dir);
                        if (ret)
-                               return ret;
+                               goto out;
                }
        }
 
-       *index = dir->index_cnt;
+       /* index_cnt is the index number of next new entry, so decrement it. */
+       *index = dir->index_cnt - 1;
+out:
+       btrfs_inode_unlock(dir, 0);
 
-       return 0;
+       return ret;
 }
 
 /*
@@ -5817,6 +5817,19 @@ static int btrfs_opendir(struct inode *inode, struct file *file)
        return 0;
 }
 
+static loff_t btrfs_dir_llseek(struct file *file, loff_t offset, int whence)
+{
+       struct btrfs_file_private *private = file->private_data;
+       int ret;
+
+       ret = btrfs_get_dir_last_index(BTRFS_I(file_inode(file)),
+                                      &private->last_index);
+       if (ret)
+               return ret;
+
+       return generic_file_llseek(file, offset, whence);
+}
+
 struct dir_entry {
        u64 ino;
        u64 offset;
@@ -10868,7 +10881,7 @@ static const struct inode_operations btrfs_dir_inode_operations = {
 };
 
 static const struct file_operations btrfs_dir_file_operations = {
-       .llseek         = generic_file_llseek,
+       .llseek         = btrfs_dir_llseek,
        .read           = generic_read_dir,
        .iterate_shared = btrfs_real_readdir,
        .open           = btrfs_opendir,
index a18ee7b5a166649141e9570dee5a45b366537b04..75ab766fe156550afef8135892dda7f3524aa948 100644 (file)
@@ -1958,6 +1958,13 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap,
                                goto out_put;
                        }
 
+                       /*
+                        * We don't need the path anymore, so release it and
+                        * avoid deadlocks and lockdep warnings in case
+                        * btrfs_iget() needs to lookup the inode from its root
+                        * btree and lock the same leaf.
+                        */
+                       btrfs_release_path(path);
                        temp_inode = btrfs_iget(sb, key2.objectid, root);
                        if (IS_ERR(temp_inode)) {
                                ret = PTR_ERR(temp_inode);
@@ -1978,7 +1985,6 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap,
                                goto out_put;
                        }
 
-                       btrfs_release_path(path);
                        key.objectid = key.offset;
                        key.offset = (u64)-1;
                        dirid = key.objectid;
index edb9b4a0dba15d7e444da3f2945138d1aaa4881e..7d6ee1e609bf2bec62338ac11aa088652997c177 100644 (file)
@@ -79,7 +79,7 @@ enum btrfs_lock_nesting {
 };
 
 enum btrfs_lockdep_trans_states {
-       BTRFS_LOCKDEP_TRANS_COMMIT_START,
+       BTRFS_LOCKDEP_TRANS_COMMIT_PREP,
        BTRFS_LOCKDEP_TRANS_UNBLOCKED,
        BTRFS_LOCKDEP_TRANS_SUPER_COMMITTED,
        BTRFS_LOCKDEP_TRANS_COMPLETED,
index b46ab348e8e5b72773a168cea943ca9abb94cc75..345c449d588ccbdfb4e3b7cf430bd9cd6392a87f 100644 (file)
@@ -639,7 +639,7 @@ void btrfs_remove_ordered_extent(struct btrfs_inode *btrfs_inode,
                        refcount_inc(&trans->use_count);
                spin_unlock(&fs_info->trans_lock);
 
-               ASSERT(trans);
+               ASSERT(trans || BTRFS_FS_ERROR(fs_info));
                if (trans) {
                        if (atomic_dec_and_test(&trans->pending_ordered))
                                wake_up(&trans->pending_wait);
index 09bfe68d2ea3fcc8ca68da3deaf3b9a3ea87342d..cffdd6f7f8e8bb0e46bdbd30128d4b8795574d65 100644 (file)
@@ -2150,7 +2150,7 @@ static struct file_system_type btrfs_fs_type = {
        .name           = "btrfs",
        .mount          = btrfs_mount,
        .kill_sb        = btrfs_kill_super,
-       .fs_flags       = FS_REQUIRES_DEV | FS_BINARY_MOUNTDATA | FS_MGTIME,
+       .fs_flags       = FS_REQUIRES_DEV | FS_BINARY_MOUNTDATA,
 };
 
 static struct file_system_type btrfs_root_fs_type = {
@@ -2158,8 +2158,7 @@ static struct file_system_type btrfs_root_fs_type = {
        .name           = "btrfs",
        .mount          = btrfs_mount_root,
        .kill_sb        = btrfs_kill_super,
-       .fs_flags       = FS_REQUIRES_DEV | FS_BINARY_MOUNTDATA |
-                         FS_ALLOW_IDMAP | FS_MGTIME,
+       .fs_flags       = FS_REQUIRES_DEV | FS_BINARY_MOUNTDATA | FS_ALLOW_IDMAP,
 };
 
 MODULE_ALIAS_FS("btrfs");
index 874e4394df860d379a4b766ae40135343bd08db1..0bf42dccb0412d80db1250259ced8066deda7848 100644 (file)
@@ -56,12 +56,17 @@ static struct kmem_cache *btrfs_trans_handle_cachep;
  * |  Call btrfs_commit_transaction() on any trans handle attached to
  * |  transaction N
  * V
- * Transaction N [[TRANS_STATE_COMMIT_START]]
+ * Transaction N [[TRANS_STATE_COMMIT_PREP]]
+ * |
+ * | If there are simultaneous calls to btrfs_commit_transaction() one will win
+ * | the race and the rest will wait for the winner to commit the transaction.
+ * |
+ * | The winner will wait for previous running transaction to completely finish
+ * | if there is one.
  * |
- * | Will wait for previous running transaction to completely finish if there
- * | is one
+ * Transaction N [[TRANS_STATE_COMMIT_START]]
  * |
- * | Then one of the following happes:
+ * | Then one of the following happens:
  * | - Wait for all other trans handle holders to release.
  * |   The btrfs_commit_transaction() caller will do the commit work.
  * | - Wait for current transaction to be committed by others.
@@ -112,6 +117,7 @@ static struct kmem_cache *btrfs_trans_handle_cachep;
  */
 static const unsigned int btrfs_blocked_trans_types[TRANS_STATE_MAX] = {
        [TRANS_STATE_RUNNING]           = 0U,
+       [TRANS_STATE_COMMIT_PREP]       = 0U,
        [TRANS_STATE_COMMIT_START]      = (__TRANS_START | __TRANS_ATTACH),
        [TRANS_STATE_COMMIT_DOING]      = (__TRANS_START |
                                           __TRANS_ATTACH |
@@ -1982,7 +1988,7 @@ void btrfs_commit_transaction_async(struct btrfs_trans_handle *trans)
         * Wait for the current transaction commit to start and block
         * subsequent transaction joins
         */
-       btrfs_might_wait_for_state(fs_info, BTRFS_LOCKDEP_TRANS_COMMIT_START);
+       btrfs_might_wait_for_state(fs_info, BTRFS_LOCKDEP_TRANS_COMMIT_PREP);
        wait_event(fs_info->transaction_blocked_wait,
                   cur_trans->state >= TRANS_STATE_COMMIT_START ||
                   TRANS_ABORTED(cur_trans));
@@ -2129,7 +2135,7 @@ static void add_pending_snapshot(struct btrfs_trans_handle *trans)
                return;
 
        lockdep_assert_held(&trans->fs_info->trans_lock);
-       ASSERT(cur_trans->state >= TRANS_STATE_COMMIT_START);
+       ASSERT(cur_trans->state >= TRANS_STATE_COMMIT_PREP);
 
        list_add(&trans->pending_snapshot->list, &cur_trans->pending_snapshots);
 }
@@ -2153,7 +2159,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
        ktime_t interval;
 
        ASSERT(refcount_read(&trans->use_count) == 1);
-       btrfs_trans_state_lockdep_acquire(fs_info, BTRFS_LOCKDEP_TRANS_COMMIT_START);
+       btrfs_trans_state_lockdep_acquire(fs_info, BTRFS_LOCKDEP_TRANS_COMMIT_PREP);
 
        clear_bit(BTRFS_FS_NEED_TRANS_COMMIT, &fs_info->flags);
 
@@ -2213,7 +2219,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
        }
 
        spin_lock(&fs_info->trans_lock);
-       if (cur_trans->state >= TRANS_STATE_COMMIT_START) {
+       if (cur_trans->state >= TRANS_STATE_COMMIT_PREP) {
                enum btrfs_trans_state want_state = TRANS_STATE_COMPLETED;
 
                add_pending_snapshot(trans);
@@ -2225,7 +2231,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
                        want_state = TRANS_STATE_SUPER_COMMITTED;
 
                btrfs_trans_state_lockdep_release(fs_info,
-                                                 BTRFS_LOCKDEP_TRANS_COMMIT_START);
+                                                 BTRFS_LOCKDEP_TRANS_COMMIT_PREP);
                ret = btrfs_end_transaction(trans);
                wait_for_commit(cur_trans, want_state);
 
@@ -2237,9 +2243,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
                return ret;
        }
 
-       cur_trans->state = TRANS_STATE_COMMIT_START;
+       cur_trans->state = TRANS_STATE_COMMIT_PREP;
        wake_up(&fs_info->transaction_blocked_wait);
-       btrfs_trans_state_lockdep_release(fs_info, BTRFS_LOCKDEP_TRANS_COMMIT_START);
+       btrfs_trans_state_lockdep_release(fs_info, BTRFS_LOCKDEP_TRANS_COMMIT_PREP);
 
        if (cur_trans->list.prev != &fs_info->trans_list) {
                enum btrfs_trans_state want_state = TRANS_STATE_COMPLETED;
@@ -2260,11 +2266,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
                        btrfs_put_transaction(prev_trans);
                        if (ret)
                                goto lockdep_release;
-               } else {
-                       spin_unlock(&fs_info->trans_lock);
+                       spin_lock(&fs_info->trans_lock);
                }
        } else {
-               spin_unlock(&fs_info->trans_lock);
                /*
                 * The previous transaction was aborted and was already removed
                 * from the list of transactions at fs_info->trans_list. So we
@@ -2272,11 +2276,16 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
                 * corrupt state (pointing to trees with unwritten nodes/leafs).
                 */
                if (BTRFS_FS_ERROR(fs_info)) {
+                       spin_unlock(&fs_info->trans_lock);
                        ret = -EROFS;
                        goto lockdep_release;
                }
        }
 
+       cur_trans->state = TRANS_STATE_COMMIT_START;
+       wake_up(&fs_info->transaction_blocked_wait);
+       spin_unlock(&fs_info->trans_lock);
+
        /*
         * Get the time spent on the work done by the commit thread and not
         * the time spent waiting on a previous commit
@@ -2586,7 +2595,7 @@ lockdep_release:
        goto cleanup_transaction;
 
 lockdep_trans_commit_start_release:
-       btrfs_trans_state_lockdep_release(fs_info, BTRFS_LOCKDEP_TRANS_COMMIT_START);
+       btrfs_trans_state_lockdep_release(fs_info, BTRFS_LOCKDEP_TRANS_COMMIT_PREP);
        btrfs_end_transaction(trans);
        return ret;
 }
index 8e9fa23bd7fed73acffeafc4b3655c6b64c7a58f..6b309f8a99a860b424865ee6656881037eb9329a 100644 (file)
@@ -14,6 +14,7 @@
 
 enum btrfs_trans_state {
        TRANS_STATE_RUNNING,
+       TRANS_STATE_COMMIT_PREP,
        TRANS_STATE_COMMIT_START,
        TRANS_STATE_COMMIT_DOING,
        TRANS_STATE_UNBLOCKED,
index c5ff16f9e9fa53aaa8779059a903f9bd636ceb02..744f4f4d4c681139648cbb04394cf6d7bce572c9 100644 (file)
@@ -715,7 +715,7 @@ static struct page *btrfs_read_merkle_tree_page(struct inode *inode,
                                                pgoff_t index,
                                                unsigned long num_ra_pages)
 {
-       struct page *page;
+       struct folio *folio;
        u64 off = (u64)index << PAGE_SHIFT;
        loff_t merkle_pos = merkle_file_pos(inode);
        int ret;
@@ -726,29 +726,36 @@ static struct page *btrfs_read_merkle_tree_page(struct inode *inode,
                return ERR_PTR(-EFBIG);
        index += merkle_pos >> PAGE_SHIFT;
 again:
-       page = find_get_page_flags(inode->i_mapping, index, FGP_ACCESSED);
-       if (page) {
-               if (PageUptodate(page))
-                       return page;
+       folio = __filemap_get_folio(inode->i_mapping, index, FGP_ACCESSED, 0);
+       if (!IS_ERR(folio)) {
+               if (folio_test_uptodate(folio))
+                       goto out;
 
-               lock_page(page);
-               /*
-                * We only insert uptodate pages, so !Uptodate has to be
-                * an error
-                */
-               if (!PageUptodate(page)) {
-                       unlock_page(page);
-                       put_page(page);
+               folio_lock(folio);
+               /* If it's not uptodate after we have the lock, we got a read error. */
+               if (!folio_test_uptodate(folio)) {
+                       folio_unlock(folio);
+                       folio_put(folio);
                        return ERR_PTR(-EIO);
                }
-               unlock_page(page);
-               return page;
+               folio_unlock(folio);
+               goto out;
        }
 
-       page = __page_cache_alloc(mapping_gfp_constraint(inode->i_mapping, ~__GFP_FS));
-       if (!page)
+       folio = filemap_alloc_folio(mapping_gfp_constraint(inode->i_mapping, ~__GFP_FS),
+                                   0);
+       if (!folio)
                return ERR_PTR(-ENOMEM);
 
+       ret = filemap_add_folio(inode->i_mapping, folio, index, GFP_NOFS);
+       if (ret) {
+               folio_put(folio);
+               /* Did someone else insert a folio here? */
+               if (ret == -EEXIST)
+                       goto again;
+               return ERR_PTR(ret);
+       }
+
        /*
         * Merkle item keys are indexed from byte 0 in the merkle tree.
         * They have the form:
@@ -756,28 +763,19 @@ again:
         * [ inode objectid, BTRFS_MERKLE_ITEM_KEY, offset in bytes ]
         */
        ret = read_key_bytes(BTRFS_I(inode), BTRFS_VERITY_MERKLE_ITEM_KEY, off,
-                            page_address(page), PAGE_SIZE, page);
+                            folio_address(folio), PAGE_SIZE, &folio->page);
        if (ret < 0) {
-               put_page(page);
+               folio_put(folio);
                return ERR_PTR(ret);
        }
        if (ret < PAGE_SIZE)
-               memzero_page(page, ret, PAGE_SIZE - ret);
+               folio_zero_segment(folio, ret, PAGE_SIZE);
 
-       SetPageUptodate(page);
-       ret = add_to_page_cache_lru(page, inode->i_mapping, index, GFP_NOFS);
+       folio_mark_uptodate(folio);
+       folio_unlock(folio);
 
-       if (!ret) {
-               /* Inserted and ready for fsverity */
-               unlock_page(page);
-       } else {
-               put_page(page);
-               /* Did someone race us into inserting this page? */
-               if (ret == -EEXIST)
-                       goto again;
-               page = ERR_PTR(ret);
-       }
-       return page;
+out:
+       return folio_file_page(folio, index);
 }
 
 /*
index 2379564e5aeadf5bebc786375d17b744cacd5f75..a6785cd07081cb363e029be686cf1877d1841243 100644 (file)
@@ -2011,7 +2011,7 @@ void folio_zero_new_buffers(struct folio *folio, size_t from, size_t to)
 }
 EXPORT_SYMBOL(folio_zero_new_buffers);
 
-static void
+static int
 iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh,
                const struct iomap *iomap)
 {
@@ -2025,7 +2025,8 @@ iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh,
         * current block, then do not map the buffer and let the caller
         * handle it.
         */
-       BUG_ON(offset >= iomap->offset + iomap->length);
+       if (offset >= iomap->offset + iomap->length)
+               return -EIO;
 
        switch (iomap->type) {
        case IOMAP_HOLE:
@@ -2037,7 +2038,7 @@ iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh,
                if (!buffer_uptodate(bh) ||
                    (offset >= i_size_read(inode)))
                        set_buffer_new(bh);
-               break;
+               return 0;
        case IOMAP_DELALLOC:
                if (!buffer_uptodate(bh) ||
                    (offset >= i_size_read(inode)))
@@ -2045,7 +2046,7 @@ iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh,
                set_buffer_uptodate(bh);
                set_buffer_mapped(bh);
                set_buffer_delay(bh);
-               break;
+               return 0;
        case IOMAP_UNWRITTEN:
                /*
                 * For unwritten regions, we always need to ensure that regions
@@ -2062,7 +2063,10 @@ iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh,
                bh->b_blocknr = (iomap->addr + offset - iomap->offset) >>
                                inode->i_blkbits;
                set_buffer_mapped(bh);
-               break;
+               return 0;
+       default:
+               WARN_ON_ONCE(1);
+               return -EIO;
        }
 }
 
@@ -2103,13 +2107,12 @@ int __block_write_begin_int(struct folio *folio, loff_t pos, unsigned len,
                        clear_buffer_new(bh);
                if (!buffer_mapped(bh)) {
                        WARN_ON(bh->b_size != blocksize);
-                       if (get_block) {
+                       if (get_block)
                                err = get_block(inode, block, bh, 1);
-                               if (err)
-                                       break;
-                       } else {
-                               iomap_to_bh(inode, block, bh, iomap);
-                       }
+                       else
+                               err = iomap_to_bh(inode, block, bh, iomap);
+                       if (err)
+                               break;
 
                        if (buffer_new(bh)) {
                                clean_bdev_bh_alias(bh);
index e028fafa04f38c51739bb56c796bb5d854c7c4ba..996271473609a0dbde8cd3db3eadb73e35d2510d 100644 (file)
@@ -32,10 +32,16 @@ static int efivarfs_statfs(struct dentry *dentry, struct kstatfs *buf)
        u64 storage_space, remaining_space, max_variable_size;
        efi_status_t status;
 
-       status = efivar_query_variable_info(attr, &storage_space, &remaining_space,
-                                           &max_variable_size);
-       if (status != EFI_SUCCESS)
-               return efi_status_to_err(status);
+       /* Some UEFI firmware does not implement QueryVariableInfo() */
+       storage_space = remaining_space = 0;
+       if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) {
+               status = efivar_query_variable_info(attr, &storage_space,
+                                                   &remaining_space,
+                                                   &max_variable_size);
+               if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED)
+                       pr_warn_ratelimited("query_variable_info() failed: 0x%lx\n",
+                                           status);
+       }
 
        /*
         * This is not a normal filesystem, so no point in pretending it has a block
index c91db9f57524c4eef9c8c33bb195721784969e7b..1e599305d85fa2b0a4356c2ac9cd4eef905ab456 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/nospec.h>
 #include <linux/backing-dev.h>
+#include <linux/freezer.h>
 #include <trace/events/ext4.h>
 
 /*
@@ -6906,6 +6907,21 @@ __acquires(bitlock)
        return ret;
 }
 
+static ext4_grpblk_t ext4_last_grp_cluster(struct super_block *sb,
+                                          ext4_group_t grp)
+{
+       if (grp < ext4_get_groups_count(sb))
+               return EXT4_CLUSTERS_PER_GROUP(sb) - 1;
+       return (ext4_blocks_count(EXT4_SB(sb)->s_es) -
+               ext4_group_first_block_no(sb, grp) - 1) >>
+                                       EXT4_CLUSTER_BITS(sb);
+}
+
+static bool ext4_trim_interrupted(void)
+{
+       return fatal_signal_pending(current) || freezing(current);
+}
+
 static int ext4_try_to_trim_range(struct super_block *sb,
                struct ext4_buddy *e4b, ext4_grpblk_t start,
                ext4_grpblk_t max, ext4_grpblk_t minblocks)
@@ -6913,9 +6929,12 @@ __acquires(ext4_group_lock_ptr(sb, e4b->bd_group))
 __releases(ext4_group_lock_ptr(sb, e4b->bd_group))
 {
        ext4_grpblk_t next, count, free_count;
+       bool set_trimmed = false;
        void *bitmap;
 
        bitmap = e4b->bd_bitmap;
+       if (start == 0 && max >= ext4_last_grp_cluster(sb, e4b->bd_group))
+               set_trimmed = true;
        start = max(e4b->bd_info->bb_first_free, start);
        count = 0;
        free_count = 0;
@@ -6930,16 +6949,14 @@ __releases(ext4_group_lock_ptr(sb, e4b->bd_group))
                        int ret = ext4_trim_extent(sb, start, next - start, e4b);
 
                        if (ret && ret != -EOPNOTSUPP)
-                               break;
+                               return count;
                        count += next - start;
                }
                free_count += next - start;
                start = next + 1;
 
-               if (fatal_signal_pending(current)) {
-                       count = -ERESTARTSYS;
-                       break;
-               }
+               if (ext4_trim_interrupted())
+                       return count;
 
                if (need_resched()) {
                        ext4_unlock_group(sb, e4b->bd_group);
@@ -6951,6 +6968,9 @@ __releases(ext4_group_lock_ptr(sb, e4b->bd_group))
                        break;
        }
 
+       if (set_trimmed)
+               EXT4_MB_GRP_SET_TRIMMED(e4b->bd_info);
+
        return count;
 }
 
@@ -6961,7 +6981,6 @@ __releases(ext4_group_lock_ptr(sb, e4b->bd_group))
  * @start:             first group block to examine
  * @max:               last group block to examine
  * @minblocks:         minimum extent block count
- * @set_trimmed:       set the trimmed flag if at least one block is trimmed
  *
  * ext4_trim_all_free walks through group's block bitmap searching for free
  * extents. When the free extent is found, mark it as used in group buddy
@@ -6971,7 +6990,7 @@ __releases(ext4_group_lock_ptr(sb, e4b->bd_group))
 static ext4_grpblk_t
 ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
                   ext4_grpblk_t start, ext4_grpblk_t max,
-                  ext4_grpblk_t minblocks, bool set_trimmed)
+                  ext4_grpblk_t minblocks)
 {
        struct ext4_buddy e4b;
        int ret;
@@ -6988,13 +7007,10 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
        ext4_lock_group(sb, group);
 
        if (!EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) ||
-           minblocks < EXT4_SB(sb)->s_last_trim_minblks) {
+           minblocks < EXT4_SB(sb)->s_last_trim_minblks)
                ret = ext4_try_to_trim_range(sb, &e4b, start, max, minblocks);
-               if (ret >= 0 && set_trimmed)
-                       EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info);
-       } else {
+       else
                ret = 0;
-       }
 
        ext4_unlock_group(sb, group);
        ext4_mb_unload_buddy(&e4b);
@@ -7027,7 +7043,6 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
        ext4_fsblk_t first_data_blk =
                        le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
        ext4_fsblk_t max_blks = ext4_blocks_count(EXT4_SB(sb)->s_es);
-       bool whole_group, eof = false;
        int ret = 0;
 
        start = range->start >> sb->s_blocksize_bits;
@@ -7046,10 +7061,8 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
                if (minlen > EXT4_CLUSTERS_PER_GROUP(sb))
                        goto out;
        }
-       if (end >= max_blks - 1) {
+       if (end >= max_blks - 1)
                end = max_blks - 1;
-               eof = true;
-       }
        if (end <= first_data_blk)
                goto out;
        if (start < first_data_blk)
@@ -7063,9 +7076,10 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
 
        /* end now represents the last cluster to discard in this group */
        end = EXT4_CLUSTERS_PER_GROUP(sb) - 1;
-       whole_group = true;
 
        for (group = first_group; group <= last_group; group++) {
+               if (ext4_trim_interrupted())
+                       break;
                grp = ext4_get_group_info(sb, group);
                if (!grp)
                        continue;
@@ -7082,13 +7096,11 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
                 * change it for the last group, note that last_cluster is
                 * already computed earlier by ext4_get_group_no_and_offset()
                 */
-               if (group == last_group) {
+               if (group == last_group)
                        end = last_cluster;
-                       whole_group = eof ? true : end == EXT4_CLUSTERS_PER_GROUP(sb) - 1;
-               }
                if (grp->bb_free >= minlen) {
                        cnt = ext4_trim_all_free(sb, group, first_cluster,
-                                                end, minlen, whole_group);
+                                                end, minlen);
                        if (cnt < 0) {
                                ret = cnt;
                                break;
index 41a6411c600b1cba08ed24b667913a563f2d3b90..bbda587f76b85ab0a6840c4cf19b45151ea3f26b 100644 (file)
@@ -343,17 +343,17 @@ static struct ext4_dir_entry_tail *get_dirent_tail(struct inode *inode,
                                                   struct buffer_head *bh)
 {
        struct ext4_dir_entry_tail *t;
+       int blocksize = EXT4_BLOCK_SIZE(inode->i_sb);
 
 #ifdef PARANOID
        struct ext4_dir_entry *d, *top;
 
        d = (struct ext4_dir_entry *)bh->b_data;
        top = (struct ext4_dir_entry *)(bh->b_data +
-               (EXT4_BLOCK_SIZE(inode->i_sb) -
-                sizeof(struct ext4_dir_entry_tail)));
-       while (d < top && d->rec_len)
+               (blocksize - sizeof(struct ext4_dir_entry_tail)));
+       while (d < top && ext4_rec_len_from_disk(d->rec_len, blocksize))
                d = (struct ext4_dir_entry *)(((void *)d) +
-                   le16_to_cpu(d->rec_len));
+                   ext4_rec_len_from_disk(d->rec_len, blocksize));
 
        if (d != top)
                return NULL;
@@ -364,7 +364,8 @@ static struct ext4_dir_entry_tail *get_dirent_tail(struct inode *inode,
 #endif
 
        if (t->det_reserved_zero1 ||
-           le16_to_cpu(t->det_rec_len) != sizeof(struct ext4_dir_entry_tail) ||
+           (ext4_rec_len_from_disk(t->det_rec_len, blocksize) !=
+            sizeof(struct ext4_dir_entry_tail)) ||
            t->det_reserved_zero2 ||
            t->det_reserved_ft != EXT4_FT_DIR_CSUM)
                return NULL;
@@ -445,13 +446,14 @@ static struct dx_countlimit *get_dx_countlimit(struct inode *inode,
        struct ext4_dir_entry *dp;
        struct dx_root_info *root;
        int count_offset;
+       int blocksize = EXT4_BLOCK_SIZE(inode->i_sb);
+       unsigned int rlen = ext4_rec_len_from_disk(dirent->rec_len, blocksize);
 
-       if (le16_to_cpu(dirent->rec_len) == EXT4_BLOCK_SIZE(inode->i_sb))
+       if (rlen == blocksize)
                count_offset = 8;
-       else if (le16_to_cpu(dirent->rec_len) == 12) {
+       else if (rlen == 12) {
                dp = (struct ext4_dir_entry *)(((void *)dirent) + 12);
-               if (le16_to_cpu(dp->rec_len) !=
-                   EXT4_BLOCK_SIZE(inode->i_sb) - 12)
+               if (ext4_rec_len_from_disk(dp->rec_len, blocksize) != blocksize - 12)
                        return NULL;
                root = (struct dx_root_info *)(((void *)dp + 12));
                if (root->reserved_zero ||
@@ -1315,6 +1317,7 @@ static int dx_make_map(struct inode *dir, struct buffer_head *bh,
        unsigned int buflen = bh->b_size;
        char *base = bh->b_data;
        struct dx_hash_info h = *hinfo;
+       int blocksize = EXT4_BLOCK_SIZE(dir->i_sb);
 
        if (ext4_has_metadata_csum(dir->i_sb))
                buflen -= sizeof(struct ext4_dir_entry_tail);
@@ -1335,11 +1338,12 @@ static int dx_make_map(struct inode *dir, struct buffer_head *bh,
                        map_tail--;
                        map_tail->hash = h.hash;
                        map_tail->offs = ((char *) de - base)>>2;
-                       map_tail->size = le16_to_cpu(de->rec_len);
+                       map_tail->size = ext4_rec_len_from_disk(de->rec_len,
+                                                               blocksize);
                        count++;
                        cond_resched();
                }
-               de = ext4_next_entry(de, dir->i_sb->s_blocksize);
+               de = ext4_next_entry(de, blocksize);
        }
        return count;
 }
index 38217422f938833f2eb9312f80da735190080dd6..dbebd8b3127e514e7dc165ced48da0b6ff3cd7da 100644 (file)
@@ -7314,7 +7314,7 @@ static struct file_system_type ext4_fs_type = {
        .init_fs_context        = ext4_init_fs_context,
        .parameters             = ext4_param_specs,
        .kill_sb                = ext4_kill_sb,
-       .fs_flags               = FS_REQUIRES_DEV | FS_ALLOW_IDMAP | FS_MGTIME,
+       .fs_flags               = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
 };
 MODULE_ALIAS_FS("ext4");
 
index 9cbf8d98489a4a67b05c8e2cfae16d34aeb594d9..4a280be229a6517b3a9bdd219051b0967af0249f 100644 (file)
@@ -2010,7 +2010,9 @@ static long gfs2_scan_glock_lru(int nr)
                if (!test_bit(GLF_LOCK, &gl->gl_flags)) {
                        if (!spin_trylock(&gl->gl_lockref.lock))
                                continue;
-                       if (!gl->gl_lockref.count) {
+                       if (gl->gl_lockref.count <= 1 &&
+                           (gl->gl_state == LM_ST_UNLOCKED ||
+                            demote_ok(gl))) {
                                list_move(&gl->gl_lru, &dispose);
                                atomic_dec(&lru_count);
                                freed++;
index d26759a98b1074d417be5ecf2c1c52e934af73fd..f41ca89d216bc243a405b70482301649098fcba0 100644 (file)
@@ -567,15 +567,16 @@ static void freeze_go_callback(struct gfs2_glock *gl, bool remote)
        struct super_block *sb = sdp->sd_vfs;
 
        if (!remote ||
-           gl->gl_state != LM_ST_SHARED ||
+           (gl->gl_state != LM_ST_SHARED &&
+            gl->gl_state != LM_ST_UNLOCKED) ||
            gl->gl_demote_state != LM_ST_UNLOCKED)
                return;
 
        /*
         * Try to get an active super block reference to prevent racing with
-        * unmount (see trylock_super()).  But note that unmount isn't the only
-        * place where a write lock on s_umount is taken, and we can fail here
-        * because of things like remount as well.
+        * unmount (see super_trylock_shared()).  But note that unmount isn't
+        * the only place where a write lock on s_umount is taken, and we can
+        * fail here because of things like remount as well.
         */
        if (down_read_trylock(&sb->s_umount)) {
                atomic_inc(&sb->s_active);
index 21ada332d55571021bda02fb55be74da43952388..1429945215a039dad28c05de4bc419ad0ebd6b79 100644 (file)
@@ -50,7 +50,8 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip,
        ret = gfs2_quota_lock(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
        if (ret)
                return ret;
-       if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
+       if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON &&
+           sdp->sd_args.ar_quota != GFS2_QUOTA_QUIET)
                return 0;
        ret = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid, ap);
        if (ret)
index 35fd688168c553d1a270485fada1819db60c4918..84bc3c76e5ccb5d800172dfe76be3d3d80ecc2ff 100644 (file)
@@ -2102,52 +2102,10 @@ int file_remove_privs(struct file *file)
 }
 EXPORT_SYMBOL(file_remove_privs);
 
-/**
- * current_mgtime - Return FS time (possibly fine-grained)
- * @inode: inode.
- *
- * Return the current time truncated to the time granularity supported by
- * the fs, as suitable for a ctime/mtime change. If the ctime is flagged
- * as having been QUERIED, get a fine-grained timestamp.
- */
-struct timespec64 current_mgtime(struct inode *inode)
-{
-       struct timespec64 now, ctime;
-       atomic_long_t *pnsec = (atomic_long_t *)&inode->__i_ctime.tv_nsec;
-       long nsec = atomic_long_read(pnsec);
-
-       if (nsec & I_CTIME_QUERIED) {
-               ktime_get_real_ts64(&now);
-               return timestamp_truncate(now, inode);
-       }
-
-       ktime_get_coarse_real_ts64(&now);
-       now = timestamp_truncate(now, inode);
-
-       /*
-        * If we've recently fetched a fine-grained timestamp
-        * then the coarse-grained one may still be earlier than the
-        * existing ctime. Just keep the existing value if so.
-        */
-       ctime = inode_get_ctime(inode);
-       if (timespec64_compare(&ctime, &now) > 0)
-               now = ctime;
-
-       return now;
-}
-EXPORT_SYMBOL(current_mgtime);
-
-static struct timespec64 current_ctime(struct inode *inode)
-{
-       if (is_mgtime(inode))
-               return current_mgtime(inode);
-       return current_time(inode);
-}
-
 static int inode_needs_update_time(struct inode *inode)
 {
        int sync_it = 0;
-       struct timespec64 now = current_ctime(inode);
+       struct timespec64 now = current_time(inode);
        struct timespec64 ctime;
 
        /* First try to exhaust all avenues to not sync */
@@ -2578,43 +2536,9 @@ EXPORT_SYMBOL(current_time);
  */
 struct timespec64 inode_set_ctime_current(struct inode *inode)
 {
-       struct timespec64 now;
-       struct timespec64 ctime;
-
-       ctime.tv_nsec = READ_ONCE(inode->__i_ctime.tv_nsec);
-       if (!(ctime.tv_nsec & I_CTIME_QUERIED)) {
-               now = current_time(inode);
+       struct timespec64 now = current_time(inode);
 
-               /* Just copy it into place if it's not multigrain */
-               if (!is_mgtime(inode)) {
-                       inode_set_ctime_to_ts(inode, now);
-                       return now;
-               }
-
-               /*
-                * If we've recently updated with a fine-grained timestamp,
-                * then the coarse-grained one may still be earlier than the
-                * existing ctime. Just keep the existing value if so.
-                */
-               ctime.tv_sec = inode->__i_ctime.tv_sec;
-               if (timespec64_compare(&ctime, &now) > 0)
-                       return ctime;
-
-               /*
-                * Ctime updates are usually protected by the inode_lock, but
-                * we can still race with someone setting the QUERIED flag.
-                * Try to swap the new nsec value into place. If it's changed
-                * in the interim, then just go with a fine-grained timestamp.
-                */
-               if (cmpxchg(&inode->__i_ctime.tv_nsec, ctime.tv_nsec,
-                           now.tv_nsec) != ctime.tv_nsec)
-                       goto fine_grained;
-               inode->__i_ctime.tv_sec = now.tv_sec;
-               return now;
-       }
-fine_grained:
-       ktime_get_real_ts64(&now);
-       inode_set_ctime_to_ts(inode, timestamp_truncate(now, inode));
+       inode_set_ctime(inode, now.tv_sec, now.tv_nsec);
        return now;
 }
 EXPORT_SYMBOL(inode_set_ctime_current);
index ae8673ce08b16e4b4268fa3eaa76efee131155a8..644479ccefbd0f188a425817912da16627d101db 100644 (file)
@@ -640,11 +640,13 @@ static int __iomap_write_begin(const struct iomap_iter *iter, loff_t pos,
        size_t poff, plen;
 
        /*
-        * If the write completely overlaps the current folio, then
+        * If the write or zeroing completely overlaps the current folio, then
         * entire folio will be dirtied so there is no need for
         * per-block state tracking structures to be attached to this folio.
+        * For the unshare case, we must read in the ondisk contents because we
+        * are not changing pagecache contents.
         */
-       if (pos <= folio_pos(folio) &&
+       if (!(iter->flags & IOMAP_UNSHARE) && pos <= folio_pos(folio) &&
            pos + len >= folio_pos(folio) + folio_size(folio))
                return 0;
 
@@ -1261,7 +1263,6 @@ static loff_t iomap_unshare_iter(struct iomap_iter *iter)
        const struct iomap *srcmap = iomap_iter_srcmap(iter);
        loff_t pos = iter->pos;
        loff_t length = iomap_length(iter);
-       long status = 0;
        loff_t written = 0;
 
        /* don't bother with blocks that are not shared to start with */
@@ -1272,28 +1273,33 @@ static loff_t iomap_unshare_iter(struct iomap_iter *iter)
                return length;
 
        do {
-               unsigned long offset = offset_in_page(pos);
-               unsigned long bytes = min_t(loff_t, PAGE_SIZE - offset, length);
                struct folio *folio;
+               int status;
+               size_t offset;
+               size_t bytes = min_t(u64, SIZE_MAX, length);
 
                status = iomap_write_begin(iter, pos, bytes, &folio);
                if (unlikely(status))
                        return status;
-               if (iter->iomap.flags & IOMAP_F_STALE)
+               if (iomap->flags & IOMAP_F_STALE)
                        break;
 
-               status = iomap_write_end(iter, pos, bytes, bytes, folio);
-               if (WARN_ON_ONCE(status == 0))
+               offset = offset_in_folio(folio, pos);
+               if (bytes > folio_size(folio) - offset)
+                       bytes = folio_size(folio) - offset;
+
+               bytes = iomap_write_end(iter, pos, bytes, bytes, folio);
+               if (WARN_ON_ONCE(bytes == 0))
                        return -EIO;
 
                cond_resched();
 
-               pos += status;
-               written += status;
-               length -= status;
+               pos += bytes;
+               written += bytes;
+               length -= bytes;
 
                balance_dirty_pages_ratelimited(iter->inode->i_mapping);
-       } while (length);
+       } while (length > 0);
 
        return written;
 }
index 1073259902a60b47a6504d9ce4b7ae4d19d81bb0..8d6f934c3d9543d3c87a77f5ec3566df7a2b2a37 100644 (file)
@@ -298,14 +298,12 @@ static int journal_finish_inode_data_buffers(journal_t *journal,
 
 static __u32 jbd2_checksum_data(__u32 crc32_sum, struct buffer_head *bh)
 {
-       struct page *page = bh->b_page;
        char *addr;
        __u32 checksum;
 
-       addr = kmap_atomic(page);
-       checksum = crc32_be(crc32_sum,
-               (void *)(addr + offset_in_page(bh->b_data)), bh->b_size);
-       kunmap_atomic(addr);
+       addr = kmap_local_folio(bh->b_folio, bh_offset(bh));
+       checksum = crc32_be(crc32_sum, addr, bh->b_size);
+       kunmap_local(addr);
 
        return checksum;
 }
@@ -322,7 +320,6 @@ static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag,
                                    struct buffer_head *bh, __u32 sequence)
 {
        journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag;
-       struct page *page = bh->b_page;
        __u8 *addr;
        __u32 csum32;
        __be32 seq;
@@ -331,11 +328,10 @@ static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag,
                return;
 
        seq = cpu_to_be32(sequence);
-       addr = kmap_atomic(page);
+       addr = kmap_local_folio(bh->b_folio, bh_offset(bh));
        csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq));
-       csum32 = jbd2_chksum(j, csum32, addr + offset_in_page(bh->b_data),
-                            bh->b_size);
-       kunmap_atomic(addr);
+       csum32 = jbd2_chksum(j, csum32, addr, bh->b_size);
+       kunmap_local(addr);
 
        if (jbd2_has_feature_csum3(j))
                tag3->t_checksum = cpu_to_be32(csum32);
index 768fa05bcbedeb7523a8ef76c8f1155ecaf2d7f3..30dec2bd2ecc26abb8d67a66b0d04f84e08dc718 100644 (file)
@@ -1601,6 +1601,8 @@ static journal_t *journal_init_common(struct block_device *bdev,
 
 err_cleanup:
        percpu_counter_destroy(&journal->j_checkpoint_jh_count);
+       if (journal->j_chksum_driver)
+               crypto_free_shash(journal->j_chksum_driver);
        kfree(journal->j_wbuf);
        jbd2_journal_destroy_revoke(journal);
        journal_fail_superblock(journal);
index 4d1fda1f71439f46f85c265f93301518b55ef99e..5f08b5fd105a311584ffd1694667eb187f0e3975 100644 (file)
@@ -935,19 +935,15 @@ static void warn_dirty_buffer(struct buffer_head *bh)
 /* Call t_frozen trigger and copy buffer data into jh->b_frozen_data. */
 static void jbd2_freeze_jh_data(struct journal_head *jh)
 {
-       struct page *page;
-       int offset;
        char *source;
        struct buffer_head *bh = jh2bh(jh);
 
        J_EXPECT_JH(jh, buffer_uptodate(bh), "Possible IO failure.\n");
-       page = bh->b_page;
-       offset = offset_in_page(bh->b_data);
-       source = kmap_atomic(page);
+       source = kmap_local_folio(bh->b_folio, bh_offset(bh));
        /* Fire data frozen trigger just before we copy the data */
-       jbd2_buffer_frozen_trigger(jh, source + offset, jh->b_triggers);
-       memcpy(jh->b_frozen_data, source + offset, bh->b_size);
-       kunmap_atomic(source);
+       jbd2_buffer_frozen_trigger(jh, source, jh->b_triggers);
+       memcpy(jh->b_frozen_data, source, bh->b_size);
+       kunmap_local(source);
 
        /*
         * Now that the frozen data is saved off, we need to store any matching
index 3404707ddbe7302201288e793287a1de5c5e24e7..2cd3ccf4c439960053e436d63792bc5bf7a914de 100644 (file)
@@ -47,12 +47,14 @@ void netfs_rreq_unlock_folios(struct netfs_io_request *rreq)
        xas_for_each(&xas, folio, last_page) {
                loff_t pg_end;
                bool pg_failed = false;
+               bool folio_started;
 
                if (xas_retry(&xas, folio))
                        continue;
 
                pg_end = folio_pos(folio) + folio_size(folio) - 1;
 
+               folio_started = false;
                for (;;) {
                        loff_t sreq_end;
 
@@ -60,8 +62,10 @@ void netfs_rreq_unlock_folios(struct netfs_io_request *rreq)
                                pg_failed = true;
                                break;
                        }
-                       if (test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags))
+                       if (!folio_started && test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) {
                                folio_start_fscache(folio);
+                               folio_started = true;
+                       }
                        pg_failed |= subreq_failed;
                        sreq_end = subreq->start + subreq->len - 1;
                        if (pg_end < sreq_end)
index 47d892a1d363d94d13b5d7af5a529ba44136d3f9..f6c74f4246917fafce2746198622edad39022179 100644 (file)
@@ -93,12 +93,10 @@ nfs_direct_handle_truncated(struct nfs_direct_req *dreq,
                dreq->max_count = dreq_len;
                if (dreq->count > dreq_len)
                        dreq->count = dreq_len;
-
-               if (test_bit(NFS_IOHDR_ERROR, &hdr->flags))
-                       dreq->error = hdr->error;
-               else /* Clear outstanding error if this is EOF */
-                       dreq->error = 0;
        }
+
+       if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) && !dreq->error)
+               dreq->error = hdr->error;
 }
 
 static void
@@ -120,6 +118,18 @@ nfs_direct_count_bytes(struct nfs_direct_req *dreq,
                dreq->count = dreq_len;
 }
 
+static void nfs_direct_truncate_request(struct nfs_direct_req *dreq,
+                                       struct nfs_page *req)
+{
+       loff_t offs = req_offset(req);
+       size_t req_start = (size_t)(offs - dreq->io_start);
+
+       if (req_start < dreq->max_count)
+               dreq->max_count = req_start;
+       if (req_start < dreq->count)
+               dreq->count = req_start;
+}
+
 /**
  * nfs_swap_rw - NFS address space operation for swap I/O
  * @iocb: target I/O control block
@@ -488,7 +498,9 @@ static void nfs_direct_add_page_head(struct list_head *list,
        kref_get(&head->wb_kref);
 }
 
-static void nfs_direct_join_group(struct list_head *list, struct inode *inode)
+static void nfs_direct_join_group(struct list_head *list,
+                                 struct nfs_commit_info *cinfo,
+                                 struct inode *inode)
 {
        struct nfs_page *req, *subreq;
 
@@ -510,7 +522,7 @@ static void nfs_direct_join_group(struct list_head *list, struct inode *inode)
                                nfs_release_request(subreq);
                        }
                } while ((subreq = subreq->wb_this_page) != req);
-               nfs_join_page_group(req, inode);
+               nfs_join_page_group(req, cinfo, inode);
        }
 }
 
@@ -528,20 +540,15 @@ nfs_direct_write_scan_commit_list(struct inode *inode,
 static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
 {
        struct nfs_pageio_descriptor desc;
-       struct nfs_page *req, *tmp;
+       struct nfs_page *req;
        LIST_HEAD(reqs);
        struct nfs_commit_info cinfo;
-       LIST_HEAD(failed);
 
        nfs_init_cinfo_from_dreq(&cinfo, dreq);
        nfs_direct_write_scan_commit_list(dreq->inode, &reqs, &cinfo);
 
-       nfs_direct_join_group(&reqs, dreq->inode);
+       nfs_direct_join_group(&reqs, &cinfo, dreq->inode);
 
-       dreq->count = 0;
-       dreq->max_count = 0;
-       list_for_each_entry(req, &reqs, wb_list)
-               dreq->max_count += req->wb_bytes;
        nfs_clear_pnfs_ds_commit_verifiers(&dreq->ds_cinfo);
        get_dreq(dreq);
 
@@ -549,27 +556,40 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
                              &nfs_direct_write_completion_ops);
        desc.pg_dreq = dreq;
 
-       list_for_each_entry_safe(req, tmp, &reqs, wb_list) {
+       while (!list_empty(&reqs)) {
+               req = nfs_list_entry(reqs.next);
                /* Bump the transmission count */
                req->wb_nio++;
                if (!nfs_pageio_add_request(&desc, req)) {
-                       nfs_list_move_request(req, &failed);
-                       spin_lock(&cinfo.inode->i_lock);
-                       dreq->flags = 0;
-                       if (desc.pg_error < 0)
+                       spin_lock(&dreq->lock);
+                       if (dreq->error < 0) {
+                               desc.pg_error = dreq->error;
+                       } else if (desc.pg_error != -EAGAIN) {
+                               dreq->flags = 0;
+                               if (!desc.pg_error)
+                                       desc.pg_error = -EIO;
                                dreq->error = desc.pg_error;
-                       else
-                               dreq->error = -EIO;
-                       spin_unlock(&cinfo.inode->i_lock);
+                       } else
+                               dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
+                       spin_unlock(&dreq->lock);
+                       break;
                }
                nfs_release_request(req);
        }
        nfs_pageio_complete(&desc);
 
-       while (!list_empty(&failed)) {
-               req = nfs_list_entry(failed.next);
+       while (!list_empty(&reqs)) {
+               req = nfs_list_entry(reqs.next);
                nfs_list_remove_request(req);
                nfs_unlock_and_release_request(req);
+               if (desc.pg_error == -EAGAIN) {
+                       nfs_mark_request_commit(req, NULL, &cinfo, 0);
+               } else {
+                       spin_lock(&dreq->lock);
+                       nfs_direct_truncate_request(dreq, req);
+                       spin_unlock(&dreq->lock);
+                       nfs_release_request(req);
+               }
        }
 
        if (put_dreq(dreq))
@@ -589,8 +609,6 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
        if (status < 0) {
                /* Errors in commit are fatal */
                dreq->error = status;
-               dreq->max_count = 0;
-               dreq->count = 0;
                dreq->flags = NFS_ODIRECT_DONE;
        } else {
                status = dreq->error;
@@ -601,7 +619,12 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
        while (!list_empty(&data->pages)) {
                req = nfs_list_entry(data->pages.next);
                nfs_list_remove_request(req);
-               if (status >= 0 && !nfs_write_match_verf(verf, req)) {
+               if (status < 0) {
+                       spin_lock(&dreq->lock);
+                       nfs_direct_truncate_request(dreq, req);
+                       spin_unlock(&dreq->lock);
+                       nfs_release_request(req);
+               } else if (!nfs_write_match_verf(verf, req)) {
                        dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
                        /*
                         * Despite the reboot, the write was successful,
@@ -609,7 +632,7 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
                         */
                        req->wb_nio = 0;
                        nfs_mark_request_commit(req, NULL, &cinfo, 0);
-               } else /* Error or match */
+               } else
                        nfs_release_request(req);
                nfs_unlock_and_release_request(req);
        }
@@ -662,6 +685,7 @@ static void nfs_direct_write_clear_reqs(struct nfs_direct_req *dreq)
        while (!list_empty(&reqs)) {
                req = nfs_list_entry(reqs.next);
                nfs_list_remove_request(req);
+               nfs_direct_truncate_request(dreq, req);
                nfs_release_request(req);
                nfs_unlock_and_release_request(req);
        }
@@ -711,7 +735,8 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
        }
 
        nfs_direct_count_bytes(dreq, hdr);
-       if (test_bit(NFS_IOHDR_UNSTABLE_WRITES, &hdr->flags)) {
+       if (test_bit(NFS_IOHDR_UNSTABLE_WRITES, &hdr->flags) &&
+           !test_bit(NFS_IOHDR_ERROR, &hdr->flags)) {
                if (!dreq->flags)
                        dreq->flags = NFS_ODIRECT_DO_COMMIT;
                flags = dreq->flags;
@@ -755,18 +780,23 @@ static void nfs_write_sync_pgio_error(struct list_head *head, int error)
 static void nfs_direct_write_reschedule_io(struct nfs_pgio_header *hdr)
 {
        struct nfs_direct_req *dreq = hdr->dreq;
+       struct nfs_page *req;
+       struct nfs_commit_info cinfo;
 
        trace_nfs_direct_write_reschedule_io(dreq);
 
+       nfs_init_cinfo_from_dreq(&cinfo, dreq);
        spin_lock(&dreq->lock);
-       if (dreq->error == 0) {
+       if (dreq->error == 0)
                dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
-               /* fake unstable write to let common nfs resend pages */
-               hdr->verf.committed = NFS_UNSTABLE;
-               hdr->good_bytes = hdr->args.offset + hdr->args.count -
-                       hdr->io_start;
-       }
+       set_bit(NFS_IOHDR_REDO, &hdr->flags);
        spin_unlock(&dreq->lock);
+       while (!list_empty(&hdr->pages)) {
+               req = nfs_list_entry(hdr->pages.next);
+               nfs_list_remove_request(req);
+               nfs_unlock_request(req);
+               nfs_mark_request_commit(req, NULL, &cinfo, 0);
+       }
 }
 
 static const struct nfs_pgio_completion_ops nfs_direct_write_completion_ops = {
@@ -794,9 +824,11 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
 {
        struct nfs_pageio_descriptor desc;
        struct inode *inode = dreq->inode;
+       struct nfs_commit_info cinfo;
        ssize_t result = 0;
        size_t requested_bytes = 0;
        size_t wsize = max_t(size_t, NFS_SERVER(inode)->wsize, PAGE_SIZE);
+       bool defer = false;
 
        trace_nfs_direct_write_schedule_iovec(dreq);
 
@@ -837,17 +869,37 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
                                break;
                        }
 
-                       nfs_lock_request(req);
-                       if (!nfs_pageio_add_request(&desc, req)) {
-                               result = desc.pg_error;
-                               nfs_unlock_and_release_request(req);
-                               break;
-                       }
                        pgbase = 0;
                        bytes -= req_len;
                        requested_bytes += req_len;
                        pos += req_len;
                        dreq->bytes_left -= req_len;
+
+                       if (defer) {
+                               nfs_mark_request_commit(req, NULL, &cinfo, 0);
+                               continue;
+                       }
+
+                       nfs_lock_request(req);
+                       if (nfs_pageio_add_request(&desc, req))
+                               continue;
+
+                       /* Exit on hard errors */
+                       if (desc.pg_error < 0 && desc.pg_error != -EAGAIN) {
+                               result = desc.pg_error;
+                               nfs_unlock_and_release_request(req);
+                               break;
+                       }
+
+                       /* If the error is soft, defer remaining requests */
+                       nfs_init_cinfo_from_dreq(&cinfo, dreq);
+                       spin_lock(&dreq->lock);
+                       dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
+                       spin_unlock(&dreq->lock);
+                       nfs_unlock_request(req);
+                       nfs_mark_request_commit(req, NULL, &cinfo, 0);
+                       desc.pg_error = 0;
+                       defer = true;
                }
                nfs_direct_release_pages(pagevec, npages);
                kvfree(pagevec);
index 7deb3cd76abe4b623c7d79554d7c9d7506491d1b..a1dc338649062de39c72230d3a1b11f8564033bb 100644 (file)
@@ -1235,6 +1235,7 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg,
                case -EPFNOSUPPORT:
                case -EPROTONOSUPPORT:
                case -EOPNOTSUPP:
+               case -EINVAL:
                case -ECONNREFUSED:
                case -ECONNRESET:
                case -EHOSTDOWN:
index 27fb25567ce755a54e16e487379a3cd7a4f62824..11e3a285594c231c6b887dc53edbe52ef8519b23 100644 (file)
@@ -417,6 +417,8 @@ static void nfs4_add_trunk(struct nfs_client *clp, struct nfs_client *old)
                .net = old->cl_net,
                .servername = old->cl_hostname,
        };
+       int max_connect = test_bit(NFS_CS_PNFS, &clp->cl_flags) ?
+               clp->cl_max_connect : old->cl_max_connect;
 
        if (clp->cl_proto != old->cl_proto)
                return;
@@ -430,7 +432,7 @@ static void nfs4_add_trunk(struct nfs_client *clp, struct nfs_client *old)
        xprt_args.addrlen = clp_salen;
 
        rpc_clnt_add_xprt(old->cl_rpcclient, &xprt_args,
-                         rpc_clnt_test_and_add_xprt, NULL);
+                         rpc_clnt_test_and_add_xprt, &max_connect);
 }
 
 /**
@@ -1010,6 +1012,8 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
                __set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
 
        __set_bit(NFS_CS_DS, &cl_init.init_flags);
+       __set_bit(NFS_CS_PNFS, &cl_init.init_flags);
+       cl_init.max_connect = NFS_MAX_TRANSPORTS;
        /*
         * Set an authflavor equual to the MDS value. Use the MDS nfs_client
         * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
index 794343790ea8bbba5493f0374d5297c45f87dd4f..3508d82388263e3f5553c00add1a463426e2f142 100644 (file)
@@ -2703,8 +2703,12 @@ static int _nfs4_proc_open(struct nfs4_opendata *data,
                        return status;
        }
        if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) {
+               struct nfs_fh *fh = &o_res->fh;
+
                nfs4_sequence_free_slot(&o_res->seq_res);
-               nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr, NULL);
+               if (o_arg->claim == NFS4_OPEN_CLAIM_FH)
+                       fh = NFS_FH(d_inode(data->dentry));
+               nfs4_proc_getattr(server, fh, o_res->f_attr, NULL);
        }
        return 0;
 }
index f4cca8f00c0c20f6906e4e2e08ea19fc1a692e00..8c1ee1a1a28f1133039a63ea9765c7b5d417c4f9 100644 (file)
@@ -59,7 +59,8 @@ static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops;
 static const struct nfs_commit_completion_ops nfs_commit_completion_ops;
 static const struct nfs_rw_ops nfs_rw_write_ops;
 static void nfs_inode_remove_request(struct nfs_page *req);
-static void nfs_clear_request_commit(struct nfs_page *req);
+static void nfs_clear_request_commit(struct nfs_commit_info *cinfo,
+                                    struct nfs_page *req);
 static void nfs_init_cinfo_from_inode(struct nfs_commit_info *cinfo,
                                      struct inode *inode);
 static struct nfs_page *
@@ -502,8 +503,8 @@ nfs_destroy_unlinked_subrequests(struct nfs_page *destroy_list,
  * the (former) group.  All subrequests are removed from any write or commit
  * lists, unlinked from the group and destroyed.
  */
-void
-nfs_join_page_group(struct nfs_page *head, struct inode *inode)
+void nfs_join_page_group(struct nfs_page *head, struct nfs_commit_info *cinfo,
+                        struct inode *inode)
 {
        struct nfs_page *subreq;
        struct nfs_page *destroy_list = NULL;
@@ -533,7 +534,7 @@ nfs_join_page_group(struct nfs_page *head, struct inode *inode)
         * Commit list removal accounting is done after locks are dropped */
        subreq = head;
        do {
-               nfs_clear_request_commit(subreq);
+               nfs_clear_request_commit(cinfo, subreq);
                subreq = subreq->wb_this_page;
        } while (subreq != head);
 
@@ -566,8 +567,10 @@ static struct nfs_page *nfs_lock_and_join_requests(struct folio *folio)
 {
        struct inode *inode = folio_file_mapping(folio)->host;
        struct nfs_page *head;
+       struct nfs_commit_info cinfo;
        int ret;
 
+       nfs_init_cinfo_from_inode(&cinfo, inode);
        /*
         * A reference is taken only on the head request which acts as a
         * reference to the whole page group - the group will not be destroyed
@@ -584,7 +587,7 @@ static struct nfs_page *nfs_lock_and_join_requests(struct folio *folio)
                return ERR_PTR(ret);
        }
 
-       nfs_join_page_group(head, inode);
+       nfs_join_page_group(head, &cinfo, inode);
 
        return head;
 }
@@ -955,18 +958,16 @@ static void nfs_folio_clear_commit(struct folio *folio)
 }
 
 /* Called holding the request lock on @req */
-static void
-nfs_clear_request_commit(struct nfs_page *req)
+static void nfs_clear_request_commit(struct nfs_commit_info *cinfo,
+                                    struct nfs_page *req)
 {
        if (test_bit(PG_CLEAN, &req->wb_flags)) {
                struct nfs_open_context *ctx = nfs_req_openctx(req);
                struct inode *inode = d_inode(ctx->dentry);
-               struct nfs_commit_info cinfo;
 
-               nfs_init_cinfo_from_inode(&cinfo, inode);
                mutex_lock(&NFS_I(inode)->commit_mutex);
-               if (!pnfs_clear_request_commit(req, &cinfo)) {
-                       nfs_request_remove_commit_list(req, &cinfo);
+               if (!pnfs_clear_request_commit(req, cinfo)) {
+                       nfs_request_remove_commit_list(req, cinfo);
                }
                mutex_unlock(&NFS_I(inode)->commit_mutex);
                nfs_folio_clear_commit(nfs_page_to_folio(req));
index 5ca748309c262b1a82eb41981d7bc76e2520f65a..4199ede0583c7d903939e60cde9b3365a2e4bef1 100644 (file)
@@ -1058,8 +1058,8 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                             rename->rn_tname, rename->rn_tnamelen);
        if (status)
                return status;
-       set_change_info(&rename->rn_sinfo, &cstate->current_fh);
-       set_change_info(&rename->rn_tinfo, &cstate->save_fh);
+       set_change_info(&rename->rn_sinfo, &cstate->save_fh);
+       set_change_info(&rename->rn_tinfo, &cstate->current_fh);
        return nfs_ok;
 }
 
index 1582af33e204a192989970b4548dd955f2d7705b..c7af1095f6b549f67e1e04b341b013bdedf6eee2 100644 (file)
@@ -1082,11 +1082,12 @@ int nfsd_pool_stats_open(struct inode *inode, struct file *file)
 
 int nfsd_pool_stats_release(struct inode *inode, struct file *file)
 {
+       struct seq_file *seq = file->private_data;
+       struct svc_serv *serv = seq->private;
        int ret = seq_release(inode, file);
-       struct net *net = inode->i_sb->s_fs_info;
 
        mutex_lock(&nfsd_mutex);
-       nfsd_put(net);
+       svc_put(serv);
        mutex_unlock(&nfsd_mutex);
        return ret;
 }
index bae404a1bad48f8fa3611986a8bb77c77b2d8d32..d1761ec5866aa6342db3d6091bd3cc06998d5ca6 100644 (file)
@@ -618,7 +618,8 @@ static int ovl_copy_up_metadata(struct ovl_copy_up_ctx *c, struct dentry *temp)
        if (err)
                return err;
 
-       if (inode->i_flags & OVL_COPY_I_FLAGS_MASK) {
+       if (inode->i_flags & OVL_COPY_I_FLAGS_MASK &&
+           (S_ISREG(c->stat.mode) || S_ISDIR(c->stat.mode))) {
                /*
                 * Copy the fileattr inode flags that are the source of already
                 * copied i_flags
index 3b4cc633d76375e47a9811ac75d497b3959a7a04..4193633c4c7a771a880acb08d28b561080d2d8b1 100644 (file)
@@ -19,7 +19,6 @@ struct ovl_aio_req {
        struct kiocb iocb;
        refcount_t ref;
        struct kiocb *orig_iocb;
-       struct fd fd;
 };
 
 static struct kmem_cache *ovl_aio_request_cachep;
@@ -280,7 +279,7 @@ static rwf_t ovl_iocb_to_rwf(int ifl)
 static inline void ovl_aio_put(struct ovl_aio_req *aio_req)
 {
        if (refcount_dec_and_test(&aio_req->ref)) {
-               fdput(aio_req->fd);
+               fput(aio_req->iocb.ki_filp);
                kmem_cache_free(ovl_aio_request_cachep, aio_req);
        }
 }
@@ -342,10 +341,9 @@ static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter)
                if (!aio_req)
                        goto out;
 
-               aio_req->fd = real;
                real.flags = 0;
                aio_req->orig_iocb = iocb;
-               kiocb_clone(&aio_req->iocb, iocb, real.file);
+               kiocb_clone(&aio_req->iocb, iocb, get_file(real.file));
                aio_req->iocb.ki_complete = ovl_aio_rw_complete;
                refcount_set(&aio_req->ref, 2);
                ret = vfs_iocb_iter_read(real.file, &aio_req->iocb, iter);
@@ -409,10 +407,9 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)
                if (!aio_req)
                        goto out;
 
-               aio_req->fd = real;
                real.flags = 0;
                aio_req->orig_iocb = iocb;
-               kiocb_clone(&aio_req->iocb, iocb, real.file);
+               kiocb_clone(&aio_req->iocb, iocb, get_file(real.file));
                aio_req->iocb.ki_flags = ifl;
                aio_req->iocb.ki_complete = ovl_aio_rw_complete;
                refcount_set(&aio_req->ref, 2);
index 9dda7e54b2d0d98766b940701dd47a5034f2f463..9a8f32f21ff569d0dc40e1d7c31b63b9aea293bc 100644 (file)
@@ -289,9 +289,7 @@ struct proc_maps_private {
        struct inode *inode;
        struct task_struct *task;
        struct mm_struct *mm;
-#ifdef CONFIG_MMU
        struct vma_iterator iter;
-#endif
 #ifdef CONFIG_NUMA
        struct mempolicy *task_mempolicy;
 #endif
index a8ac0dd8041ebca2178ab245c6337a3b9db2cbe6..7cebd397cc26e1056d3533643c98f87a2ae5fd79 100644 (file)
@@ -175,15 +175,28 @@ static int show_map(struct seq_file *m, void *_p)
        return nommu_vma_show(m, _p);
 }
 
-static void *m_start(struct seq_file *m, loff_t *pos)
+static struct vm_area_struct *proc_get_vma(struct proc_maps_private *priv,
+                                               loff_t *ppos)
+{
+       struct vm_area_struct *vma = vma_next(&priv->iter);
+
+       if (vma) {
+               *ppos = vma->vm_start;
+       } else {
+               *ppos = -1UL;
+       }
+
+       return vma;
+}
+
+static void *m_start(struct seq_file *m, loff_t *ppos)
 {
        struct proc_maps_private *priv = m->private;
+       unsigned long last_addr = *ppos;
        struct mm_struct *mm;
-       struct vm_area_struct *vma;
-       unsigned long addr = *pos;
 
-       /* See m_next(). Zero at the start or after lseek. */
-       if (addr == -1UL)
+       /* See proc_get_vma(). Zero at the start or after lseek. */
+       if (last_addr == -1UL)
                return NULL;
 
        /* pin the task and mm whilst we play with them */
@@ -192,44 +205,41 @@ static void *m_start(struct seq_file *m, loff_t *pos)
                return ERR_PTR(-ESRCH);
 
        mm = priv->mm;
-       if (!mm || !mmget_not_zero(mm))
+       if (!mm || !mmget_not_zero(mm)) {
+               put_task_struct(priv->task);
+               priv->task = NULL;
                return NULL;
+       }
 
        if (mmap_read_lock_killable(mm)) {
                mmput(mm);
+               put_task_struct(priv->task);
+               priv->task = NULL;
                return ERR_PTR(-EINTR);
        }
 
-       /* start the next element from addr */
-       vma = find_vma(mm, addr);
-       if (vma)
-               return vma;
+       vma_iter_init(&priv->iter, mm, last_addr);
 
-       mmap_read_unlock(mm);
-       mmput(mm);
-       return NULL;
+       return proc_get_vma(priv, ppos);
 }
 
-static void m_stop(struct seq_file *m, void *_vml)
+static void m_stop(struct seq_file *m, void *v)
 {
        struct proc_maps_private *priv = m->private;
+       struct mm_struct *mm = priv->mm;
 
-       if (!IS_ERR_OR_NULL(_vml)) {
-               mmap_read_unlock(priv->mm);
-               mmput(priv->mm);
-       }
-       if (priv->task) {
-               put_task_struct(priv->task);
-               priv->task = NULL;
-       }
+       if (!priv->task)
+               return;
+
+       mmap_read_unlock(mm);
+       mmput(mm);
+       put_task_struct(priv->task);
+       priv->task = NULL;
 }
 
-static void *m_next(struct seq_file *m, void *_p, loff_t *pos)
+static void *m_next(struct seq_file *m, void *_p, loff_t *ppos)
 {
-       struct vm_area_struct *vma = _p;
-
-       *pos = vma->vm_end;
-       return find_vma(vma->vm_mm, vma->vm_end);
+       return proc_get_vma(m->private, ppos);
 }
 
 static const struct seq_operations proc_pid_maps_ops = {
index b17f067e4ada0503e61550a16e6536c96055ed96..e2be8aedb26e3a4c2a8655c9d020f76dffc71dd4 100644 (file)
@@ -452,6 +452,9 @@ void invalidate_all_cached_dirs(struct cifs_tcon *tcon)
        struct cached_fid *cfid, *q;
        LIST_HEAD(entry);
 
+       if (cfids == NULL)
+               return;
+
        spin_lock(&cfids->cfid_list_lock);
        list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
                list_move(&cfid->entry, &entry);
@@ -651,6 +654,9 @@ void free_cached_dirs(struct cached_fids *cfids)
        struct cached_fid *cfid, *q;
        LIST_HEAD(entry);
 
+       if (cfids == NULL)
+               return;
+
        if (cfids->laundromat) {
                kthread_stop(cfids->laundromat);
                cfids->laundromat = NULL;
index 032d8716f6719cb0084d90aa9145b29c4a55cb03..02082621d8e07a8682095516d94f440728a74f76 100644 (file)
@@ -1807,6 +1807,7 @@ static inline bool is_retryable_error(int error)
 #define   MID_RETRY_NEEDED      8 /* session closed while this request out */
 #define   MID_RESPONSE_MALFORMED 0x10
 #define   MID_SHUTDOWN          0x20
+#define   MID_RESPONSE_READY 0x40 /* ready for other process handle the rsp */
 
 /* Flags */
 #define   MID_WAIT_CANCELLED    1 /* Cancelled while waiting for response */
@@ -1943,7 +1944,7 @@ require use of the stronger protocol */
  * cifsInodeInfo->lock_sem     cifsInodeInfo->llist            cifs_init_once
  *                             ->can_cache_brlcks
  * cifsInodeInfo->deferred_lock        cifsInodeInfo->deferred_closes  cifsInodeInfo_alloc
- * cached_fid->fid_mutex               cifs_tcon->crfid                tconInfoAlloc
+ * cached_fid->fid_mutex               cifs_tcon->crfid                tcon_info_alloc
  * cifsFileInfo->fh_mutex              cifsFileInfo                    cifs_new_fileinfo
  * cifsFileInfo->file_info_lock        cifsFileInfo->count             cifs_new_fileinfo
  *                             ->invalidHandle                 initiate_cifs_search
index 7d8035846680ab224ee02300d4c0ed804a197d8c..0c37eefa18a57c0ed7be7921033ca86eda86c144 100644 (file)
@@ -512,7 +512,7 @@ extern int CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses);
 
 extern struct cifs_ses *sesInfoAlloc(void);
 extern void sesInfoFree(struct cifs_ses *);
-extern struct cifs_tcon *tconInfoAlloc(void);
+extern struct cifs_tcon *tcon_info_alloc(bool dir_leases_enabled);
 extern void tconInfoFree(struct cifs_tcon *);
 
 extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
index 687754791bf0af496029bf7ba19d3cf7c46cdae7..3902e90dca6b0521062b8432b55b23cee2f7ae54 100644 (file)
@@ -1882,7 +1882,8 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
                }
        }
 
-       tcon = tconInfoAlloc();
+       /* no need to setup directory caching on IPC share, so pass in false */
+       tcon = tcon_info_alloc(false);
        if (tcon == NULL)
                return -ENOMEM;
 
@@ -2492,7 +2493,10 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
                goto out_fail;
        }
 
-       tcon = tconInfoAlloc();
+       if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)
+               tcon = tcon_info_alloc(true);
+       else
+               tcon = tcon_info_alloc(false);
        if (tcon == NULL) {
                rc = -ENOMEM;
                goto out_fail;
index de2dfbaae821026dbdb585e2274efdc9308dfa6f..d7c302442c1ec876cb977850c74a161331ff8577 100644 (file)
@@ -2680,7 +2680,7 @@ int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
        }
 
        cifsFileInfo_put(cfile);
-       return -ENOTSUPP;
+       return -EOPNOTSUPP;
 }
 
 int cifs_truncate_page(struct address_space *mapping, loff_t from)
index 366b755ca9130df5177bd92ea7d1f940c18cbf1f..35b176457bbed02d0df438e127dc2c0482e5143c 100644 (file)
@@ -113,18 +113,22 @@ sesInfoFree(struct cifs_ses *buf_to_free)
 }
 
 struct cifs_tcon *
-tconInfoAlloc(void)
+tcon_info_alloc(bool dir_leases_enabled)
 {
        struct cifs_tcon *ret_buf;
 
        ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL);
        if (!ret_buf)
                return NULL;
-       ret_buf->cfids = init_cached_dirs();
-       if (!ret_buf->cfids) {
-               kfree(ret_buf);
-               return NULL;
+
+       if (dir_leases_enabled == true) {
+               ret_buf->cfids = init_cached_dirs();
+               if (!ret_buf->cfids) {
+                       kfree(ret_buf);
+                       return NULL;
+               }
        }
+       /* else ret_buf->cfids is already set to NULL above */
 
        atomic_inc(&tconInfoAllocCount);
        ret_buf->status = TID_NEW;
index b41e2e872b22462f2d0ee6ee14ecab0a3959654a..0b89f7008ac0f429cc1a6b004c70117e19658837 100644 (file)
@@ -539,6 +539,9 @@ static int parse_create_response(struct cifs_open_info_data *data,
        int rc = 0;
 
        switch (rsp->hdr.Status) {
+       case STATUS_IO_REPARSE_TAG_NOT_HANDLED:
+               reparse_point = true;
+               break;
        case STATUS_STOPPED_ON_SYMLINK:
                rc = smb2_parse_symlink_response(cifs_sb, iov,
                                                 &data->symlink_target);
index 194799ddd38288847dec2b2a1b65f604ec4be322..1a90dd78b238f0de191421bd0d1838164bff9778 100644 (file)
@@ -877,8 +877,6 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
        "STATUS_IO_REPARSE_TAG_MISMATCH"},
        {STATUS_IO_REPARSE_DATA_INVALID, -EIO,
        "STATUS_IO_REPARSE_DATA_INVALID"},
-       {STATUS_IO_REPARSE_TAG_NOT_HANDLED, -EIO,
-       "STATUS_IO_REPARSE_TAG_NOT_HANDLED"},
        {STATUS_REPARSE_POINT_NOT_RESOLVED, -EIO,
        "STATUS_REPARSE_POINT_NOT_RESOLVED"},
        {STATUS_DIRECTORY_IS_A_REPARSE_POINT, -EIO,
index d9eda2e958b4d03198c0b03062bb09354ad8a209..9aeecee6b91b356711d3f545119eba504e08c28e 100644 (file)
@@ -297,7 +297,7 @@ smb2_adjust_credits(struct TCP_Server_Info *server,
                cifs_server_dbg(VFS, "request has less credits (%d) than required (%d)",
                                credits->value, new_val);
 
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
        }
 
        spin_lock(&server->req_lock);
@@ -1161,7 +1161,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
                        /* Use a fudge factor of 256 bytes in case we collide
                         * with a different set_EAs command.
                         */
-                       if(CIFSMaxBufSize - MAX_SMB2_CREATE_RESPONSE_SIZE -
+                       if (CIFSMaxBufSize - MAX_SMB2_CREATE_RESPONSE_SIZE -
                           MAX_SMB2_CLOSE_RESPONSE_SIZE - 256 <
                           used_len + ea_name_len + ea_value_len + 1) {
                                rc = -ENOSPC;
@@ -4591,7 +4591,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
 
        if (shdr->Command != SMB2_READ) {
                cifs_server_dbg(VFS, "only big read responses are supported\n");
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
        }
 
        if (server->ops->is_session_expired &&
index 092b0087c9dc14441d80cc197417c410a2d86f0d..c75a80bb6d9eefa8a76e8c03baea7af8b7740c25 100644 (file)
@@ -89,20 +89,26 @@ smb2_hdr_assemble(struct smb2_hdr *shdr, __le16 smb2_cmd,
                  struct TCP_Server_Info *server)
 {
        struct smb3_hdr_req *smb3_hdr;
+
        shdr->ProtocolId = SMB2_PROTO_NUMBER;
        shdr->StructureSize = cpu_to_le16(64);
        shdr->Command = smb2_cmd;
-       if (server->dialect >= SMB30_PROT_ID) {
-               /* After reconnect SMB3 must set ChannelSequence on subsequent reqs */
-               smb3_hdr = (struct smb3_hdr_req *)shdr;
-               /* if primary channel is not set yet, use default channel for chan sequence num */
-               if (SERVER_IS_CHAN(server))
-                       smb3_hdr->ChannelSequence =
-                               cpu_to_le16(server->primary_server->channel_sequence_num);
-               else
-                       smb3_hdr->ChannelSequence = cpu_to_le16(server->channel_sequence_num);
-       }
+
        if (server) {
+               /* After reconnect SMB3 must set ChannelSequence on subsequent reqs */
+               if (server->dialect >= SMB30_PROT_ID) {
+                       smb3_hdr = (struct smb3_hdr_req *)shdr;
+                       /*
+                        * if primary channel is not set yet, use default
+                        * channel for chan sequence num
+                        */
+                       if (SERVER_IS_CHAN(server))
+                               smb3_hdr->ChannelSequence =
+                                       cpu_to_le16(server->primary_server->channel_sequence_num);
+                       else
+                               smb3_hdr->ChannelSequence =
+                                       cpu_to_le16(server->channel_sequence_num);
+               }
                spin_lock(&server->req_lock);
                /* Request up to 10 credits but don't go over the limit. */
                if (server->credits >= server->max_credits)
@@ -842,7 +848,7 @@ add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode)
 
        iov[num].iov_base = create_posix_buf(mode);
        if (mode == ACL_NO_MODE)
-               cifs_dbg(FYI, "Invalid mode\n");
+               cifs_dbg(FYI, "%s: no mode\n", __func__);
        if (iov[num].iov_base == NULL)
                return -ENOMEM;
        iov[num].iov_len = sizeof(struct create_posix);
@@ -2234,7 +2240,7 @@ create_durable_v2_buf(struct cifs_open_parms *oparms)
         * (most servers default to 120 seconds) and most clients default to 0.
         * This can be overridden at mount ("handletimeout=") if the user wants
         * a different persistent (or resilient) handle timeout for all opens
-        * opens on a particular SMB3 mount.
+        * on a particular SMB3 mount.
         */
        buf->dcontext.Timeout = cpu_to_le32(oparms->tcon->handle_timeout);
        buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
@@ -2379,7 +2385,7 @@ add_twarp_context(struct kvec *iov, unsigned int *num_iovec, __u64 timewarp)
        return 0;
 }
 
-/* See See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx */
+/* See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx */
 static void setup_owner_group_sids(char *buf)
 {
        struct owner_group_sids *sids = (struct owner_group_sids *)buf;
@@ -3124,6 +3130,7 @@ void
 SMB2_ioctl_free(struct smb_rqst *rqst)
 {
        int i;
+
        if (rqst && rqst->rq_iov) {
                cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
                for (i = 1; i < rqst->rq_nvec; i++)
@@ -3871,7 +3878,7 @@ void smb2_reconnect_server(struct work_struct *work)
                goto done;
 
        /* allocate a dummy tcon struct used for reconnect */
-       tcon = tconInfoAlloc();
+       tcon = tcon_info_alloc(false);
        if (!tcon) {
                resched = true;
                list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {
index 2a2aec8c61129b907acc7b1418e8207548e3716b..94df9eec3d8d1c240d6b4573c7fe1884ef99fdd4 100644 (file)
@@ -1401,10 +1401,13 @@ create_conn:
        server->smbd_conn = smbd_get_connection(
                server, (struct sockaddr *) &server->dstaddr);
 
-       if (server->smbd_conn)
+       if (server->smbd_conn) {
                cifs_dbg(VFS, "RDMA transport re-established\n");
-
-       return server->smbd_conn ? 0 : -ENOENT;
+               trace_smb3_smbd_connect_done(server->hostname, server->conn_id, &server->dstaddr);
+               return 0;
+       }
+       trace_smb3_smbd_connect_err(server->hostname, server->conn_id, &server->dstaddr);
+       return -ENOENT;
 }
 
 static void destroy_caches_and_workqueue(struct smbd_connection *info)
index a7e4755bed0fc240267f68f48a652ee7e9428083..de199ec9f7263daf369639d2bda1df453f225e59 100644 (file)
@@ -935,6 +935,8 @@ DEFINE_EVENT(smb3_connect_class, smb3_##name,  \
        TP_ARGS(hostname, conn_id, addr))
 
 DEFINE_SMB3_CONNECT_EVENT(connect_done);
+DEFINE_SMB3_CONNECT_EVENT(smbd_connect_done);
+DEFINE_SMB3_CONNECT_EVENT(smbd_connect_err);
 
 DECLARE_EVENT_CLASS(smb3_connect_err_class,
        TP_PROTO(char *hostname, __u64 conn_id,
index 1b5d9794ed5b0b5e5e0e63a4dadea8f8c66a6ddd..14710afdc2a36cf3715e940a77d79b5f02f7c999 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/bvec.h>
 #include <linux/highmem.h>
 #include <linux/uaccess.h>
-#include <asm/processor.h>
+#include <linux/processor.h>
 #include <linux/mempool.h>
 #include <linux/sched/signal.h>
 #include <linux/task_io_accounting_ops.h>
@@ -35,6 +35,8 @@
 void
 cifs_wake_up_task(struct mid_q_entry *mid)
 {
+       if (mid->mid_state == MID_RESPONSE_RECEIVED)
+               mid->mid_state = MID_RESPONSE_READY;
        wake_up_process(mid->callback_data);
 }
 
@@ -87,7 +89,8 @@ static void __release_mid(struct kref *refcount)
        struct TCP_Server_Info *server = midEntry->server;
 
        if (midEntry->resp_buf && (midEntry->mid_flags & MID_WAIT_CANCELLED) &&
-           midEntry->mid_state == MID_RESPONSE_RECEIVED &&
+           (midEntry->mid_state == MID_RESPONSE_RECEIVED ||
+            midEntry->mid_state == MID_RESPONSE_READY) &&
            server->ops->handle_cancelled_mid)
                server->ops->handle_cancelled_mid(midEntry, server);
 
@@ -737,7 +740,8 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
        int error;
 
        error = wait_event_state(server->response_q,
-                                midQ->mid_state != MID_REQUEST_SUBMITTED,
+                                midQ->mid_state != MID_REQUEST_SUBMITTED &&
+                                midQ->mid_state != MID_RESPONSE_RECEIVED,
                                 (TASK_KILLABLE|TASK_FREEZABLE_UNSAFE));
        if (error < 0)
                return -ERESTARTSYS;
@@ -890,7 +894,7 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
 
        spin_lock(&server->mid_lock);
        switch (mid->mid_state) {
-       case MID_RESPONSE_RECEIVED:
+       case MID_RESPONSE_READY:
                spin_unlock(&server->mid_lock);
                return rc;
        case MID_RETRY_NEEDED:
@@ -989,6 +993,9 @@ cifs_compound_callback(struct mid_q_entry *mid)
        credits.instance = server->reconnect_instance;
 
        add_credits(server, &credits, mid->optype);
+
+       if (mid->mid_state == MID_RESPONSE_RECEIVED)
+               mid->mid_state = MID_RESPONSE_READY;
 }
 
 static void
@@ -1209,7 +1216,8 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
                        send_cancel(server, &rqst[i], midQ[i]);
                        spin_lock(&server->mid_lock);
                        midQ[i]->mid_flags |= MID_WAIT_CANCELLED;
-                       if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) {
+                       if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED ||
+                           midQ[i]->mid_state == MID_RESPONSE_RECEIVED) {
                                midQ[i]->callback = cifs_cancelled_callback;
                                cancelled_mid[i] = true;
                                credits[i].value = 0;
@@ -1230,7 +1238,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
                }
 
                if (!midQ[i]->resp_buf ||
-                   midQ[i]->mid_state != MID_RESPONSE_RECEIVED) {
+                   midQ[i]->mid_state != MID_RESPONSE_READY) {
                        rc = -EIO;
                        cifs_dbg(FYI, "Bad MID state?\n");
                        goto out;
@@ -1417,7 +1425,8 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
        if (rc != 0) {
                send_cancel(server, &rqst, midQ);
                spin_lock(&server->mid_lock);
-               if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
+               if (midQ->mid_state == MID_REQUEST_SUBMITTED ||
+                   midQ->mid_state == MID_RESPONSE_RECEIVED) {
                        /* no longer considered to be "in-flight" */
                        midQ->callback = release_mid;
                        spin_unlock(&server->mid_lock);
@@ -1434,7 +1443,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
        }
 
        if (!midQ->resp_buf || !out_buf ||
-           midQ->mid_state != MID_RESPONSE_RECEIVED) {
+           midQ->mid_state != MID_RESPONSE_READY) {
                rc = -EIO;
                cifs_server_dbg(VFS, "Bad MID state?\n");
                goto out;
@@ -1558,14 +1567,16 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
 
        /* Wait for a reply - allow signals to interrupt. */
        rc = wait_event_interruptible(server->response_q,
-               (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) ||
+               (!(midQ->mid_state == MID_REQUEST_SUBMITTED ||
+                  midQ->mid_state == MID_RESPONSE_RECEIVED)) ||
                ((server->tcpStatus != CifsGood) &&
                 (server->tcpStatus != CifsNew)));
 
        /* Were we interrupted by a signal ? */
        spin_lock(&server->srv_lock);
        if ((rc == -ERESTARTSYS) &&
-               (midQ->mid_state == MID_REQUEST_SUBMITTED) &&
+               (midQ->mid_state == MID_REQUEST_SUBMITTED ||
+                midQ->mid_state == MID_RESPONSE_RECEIVED) &&
                ((server->tcpStatus == CifsGood) ||
                 (server->tcpStatus == CifsNew))) {
                spin_unlock(&server->srv_lock);
@@ -1596,7 +1607,8 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
                if (rc) {
                        send_cancel(server, &rqst, midQ);
                        spin_lock(&server->mid_lock);
-                       if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
+                       if (midQ->mid_state == MID_REQUEST_SUBMITTED ||
+                           midQ->mid_state == MID_RESPONSE_RECEIVED) {
                                /* no longer considered to be "in-flight" */
                                midQ->callback = release_mid;
                                spin_unlock(&server->mid_lock);
@@ -1616,7 +1628,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
                return rc;
 
        /* rcvd frame is ok */
-       if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) {
+       if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_READY) {
                rc = -EIO;
                cifs_tcon_dbg(VFS, "Bad MID state?\n");
                goto out;
index 749660110878fdbd75c2820a14eaf7ba543496ce..544022dd6d2007132a1bc3a310d4ee57f671a047 100644 (file)
@@ -6312,7 +6312,7 @@ int smb2_read(struct ksmbd_work *work)
                                                      aux_payload_buf,
                                                      nbytes);
                kvfree(aux_payload_buf);
-
+               aux_payload_buf = NULL;
                nbytes = 0;
                if (remain_bytes < 0) {
                        err = (int)remain_bytes;
index e5e438bf54996510da5800ea38ac50f60e36b36c..6c0305be895e56fb11464c5fe17245afc4354447 100644 (file)
@@ -1420,7 +1420,6 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
 out:
        posix_acl_release(fattr.cf_acls);
        posix_acl_release(fattr.cf_dacls);
-       mark_inode_dirty(inode);
        return rc;
 }
 
index 6822ac77aec24d00b78f67bc5a18043aa99665e1..d43a5cc1bfa46b142197c991343a295d375af60f 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
 #include "internal.h"
 #include "mount.h"
 
-/**
- * fill_mg_cmtime - Fill in the mtime and ctime and flag ctime as QUERIED
- * @stat: where to store the resulting values
- * @request_mask: STATX_* values requested
- * @inode: inode from which to grab the c/mtime
- *
- * Given @inode, grab the ctime and mtime out if it and store the result
- * in @stat. When fetching the value, flag it as queried so the next write
- * will use a fine-grained timestamp.
- */
-void fill_mg_cmtime(struct kstat *stat, u32 request_mask, struct inode *inode)
-{
-       atomic_long_t *pnsec = (atomic_long_t *)&inode->__i_ctime.tv_nsec;
-
-       /* If neither time was requested, then don't report them */
-       if (!(request_mask & (STATX_CTIME|STATX_MTIME))) {
-               stat->result_mask &= ~(STATX_CTIME|STATX_MTIME);
-               return;
-       }
-
-       stat->mtime = inode->i_mtime;
-       stat->ctime.tv_sec = inode->__i_ctime.tv_sec;
-       /*
-        * Atomically set the QUERIED flag and fetch the new value with
-        * the flag masked off.
-        */
-       stat->ctime.tv_nsec = atomic_long_fetch_or(I_CTIME_QUERIED, pnsec) &
-                                       ~I_CTIME_QUERIED;
-}
-EXPORT_SYMBOL(fill_mg_cmtime);
-
 /**
  * generic_fillattr - Fill in the basic attributes from the inode struct
  * @idmap:             idmap of the mount the inode was found from
@@ -89,14 +58,8 @@ void generic_fillattr(struct mnt_idmap *idmap, u32 request_mask,
        stat->rdev = inode->i_rdev;
        stat->size = i_size_read(inode);
        stat->atime = inode->i_atime;
-
-       if (is_mgtime(inode)) {
-               fill_mg_cmtime(stat, request_mask, inode);
-       } else {
-               stat->mtime = inode->i_mtime;
-               stat->ctime = inode_get_ctime(inode);
-       }
-
+       stat->mtime = inode->i_mtime;
+       stat->ctime = inode_get_ctime(inode);
        stat->blksize = i_blocksize(inode);
        stat->blocks = inode->i_blocks;
 
@@ -419,12 +382,6 @@ SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, stat
 
 #ifdef __ARCH_WANT_NEW_STAT
 
-#if BITS_PER_LONG == 32
-#  define choose_32_64(a,b) a
-#else
-#  define choose_32_64(a,b) b
-#endif
-
 #ifndef INIT_STRUCT_STAT_PADDING
 #  define INIT_STRUCT_STAT_PADDING(st) memset(&st, 0, sizeof(st))
 #endif
index 237c6f370ad9d55fd22fedf0c9d2f49efeb83f1a..5f17140898844919eef25daa7976aa6fbcbfc7bd 100644 (file)
@@ -70,6 +70,7 @@ static struct dentry *eventfs_root_lookup(struct inode *dir,
                                          struct dentry *dentry,
                                          unsigned int flags);
 static int dcache_dir_open_wrapper(struct inode *inode, struct file *file);
+static int dcache_readdir_wrapper(struct file *file, struct dir_context *ctx);
 static int eventfs_release(struct inode *inode, struct file *file);
 
 static const struct inode_operations eventfs_root_dir_inode_operations = {
@@ -79,7 +80,7 @@ static const struct inode_operations eventfs_root_dir_inode_operations = {
 static const struct file_operations eventfs_file_operations = {
        .open           = dcache_dir_open_wrapper,
        .read           = generic_read_dir,
-       .iterate_shared = dcache_readdir,
+       .iterate_shared = dcache_readdir_wrapper,
        .llseek         = generic_file_llseek,
        .release        = eventfs_release,
 };
@@ -185,17 +186,49 @@ static struct dentry *create_dir(const char *name, struct dentry *parent, void *
 
 /**
  * eventfs_set_ef_status_free - set the ef->status to free
+ * @ti: the tracefs_inode of the dentry
  * @dentry: dentry who's status to be freed
  *
  * eventfs_set_ef_status_free will be called if no more
  * references remain
  */
-void eventfs_set_ef_status_free(struct dentry *dentry)
+void eventfs_set_ef_status_free(struct tracefs_inode *ti, struct dentry *dentry)
 {
        struct tracefs_inode *ti_parent;
-       struct eventfs_file *ef;
+       struct eventfs_inode *ei;
+       struct eventfs_file *ef, *tmp;
+
+       /* The top level events directory may be freed by this */
+       if (unlikely(ti->flags & TRACEFS_EVENT_TOP_INODE)) {
+               LIST_HEAD(ef_del_list);
+
+               mutex_lock(&eventfs_mutex);
+
+               ei = ti->private;
+
+               /* Record all the top level files */
+               list_for_each_entry_srcu(ef, &ei->e_top_files, list,
+                                        lockdep_is_held(&eventfs_mutex)) {
+                       list_add_tail(&ef->del_list, &ef_del_list);
+               }
+
+               /* Nothing should access this, but just in case! */
+               ti->private = NULL;
+
+               mutex_unlock(&eventfs_mutex);
+
+               /* Now safely free the top level files and their children */
+               list_for_each_entry_safe(ef, tmp, &ef_del_list, del_list) {
+                       list_del(&ef->del_list);
+                       eventfs_remove(ef);
+               }
+
+               kfree(ei);
+               return;
+       }
 
        mutex_lock(&eventfs_mutex);
+
        ti_parent = get_tracefs(dentry->d_parent->d_inode);
        if (!ti_parent || !(ti_parent->flags & TRACEFS_EVENT_INODE))
                goto out;
@@ -364,6 +397,11 @@ static struct dentry *eventfs_root_lookup(struct inode *dir,
        return ret;
 }
 
+struct dentry_list {
+       void                    *cursor;
+       struct dentry           **dentries;
+};
+
 /**
  * eventfs_release - called to release eventfs file/dir
  * @inode: inode to be released
@@ -372,26 +410,25 @@ static struct dentry *eventfs_root_lookup(struct inode *dir,
 static int eventfs_release(struct inode *inode, struct file *file)
 {
        struct tracefs_inode *ti;
-       struct eventfs_inode *ei;
-       struct eventfs_file *ef;
-       struct dentry *dentry;
-       int idx;
+       struct dentry_list *dlist = file->private_data;
+       void *cursor;
+       int i;
 
        ti = get_tracefs(inode);
        if (!(ti->flags & TRACEFS_EVENT_INODE))
                return -EINVAL;
 
-       ei = ti->private;
-       idx = srcu_read_lock(&eventfs_srcu);
-       list_for_each_entry_srcu(ef, &ei->e_top_files, list,
-                                srcu_read_lock_held(&eventfs_srcu)) {
-               mutex_lock(&eventfs_mutex);
-               dentry = ef->dentry;
-               mutex_unlock(&eventfs_mutex);
-               if (dentry)
-                       dput(dentry);
+       if (WARN_ON_ONCE(!dlist))
+               return -EINVAL;
+
+       for (i = 0; dlist->dentries[i]; i++) {
+               dput(dlist->dentries[i]);
        }
-       srcu_read_unlock(&eventfs_srcu, idx);
+
+       cursor = dlist->cursor;
+       kfree(dlist->dentries);
+       kfree(dlist);
+       file->private_data = cursor;
        return dcache_dir_close(inode, file);
 }
 
@@ -410,21 +447,70 @@ static int dcache_dir_open_wrapper(struct inode *inode, struct file *file)
        struct tracefs_inode *ti;
        struct eventfs_inode *ei;
        struct eventfs_file *ef;
+       struct dentry_list *dlist;
+       struct dentry **dentries = NULL;
        struct dentry *dentry = file_dentry(file);
+       struct dentry *d;
        struct inode *f_inode = file_inode(file);
+       int cnt = 0;
        int idx;
+       int ret;
 
        ti = get_tracefs(f_inode);
        if (!(ti->flags & TRACEFS_EVENT_INODE))
                return -EINVAL;
 
+       if (WARN_ON_ONCE(file->private_data))
+               return -EINVAL;
+
+       dlist = kmalloc(sizeof(*dlist), GFP_KERNEL);
+       if (!dlist)
+               return -ENOMEM;
+
        ei = ti->private;
        idx = srcu_read_lock(&eventfs_srcu);
-       list_for_each_entry_rcu(ef, &ei->e_top_files, list) {
-               create_dentry(ef, dentry, false);
+       list_for_each_entry_srcu(ef, &ei->e_top_files, list,
+                                srcu_read_lock_held(&eventfs_srcu)) {
+               d = create_dentry(ef, dentry, false);
+               if (d) {
+                       struct dentry **tmp;
+
+                       tmp = krealloc(dentries, sizeof(d) * (cnt + 2), GFP_KERNEL);
+                       if (!tmp)
+                               break;
+                       tmp[cnt] = d;
+                       tmp[cnt + 1] = NULL;
+                       cnt++;
+                       dentries = tmp;
+               }
        }
        srcu_read_unlock(&eventfs_srcu, idx);
-       return dcache_dir_open(inode, file);
+       ret = dcache_dir_open(inode, file);
+
+       /*
+        * dcache_dir_open() sets file->private_data to a dentry cursor.
+        * Need to save that but also save all the dentries that were
+        * opened by this function.
+        */
+       dlist->cursor = file->private_data;
+       dlist->dentries = dentries;
+       file->private_data = dlist;
+       return ret;
+}
+
+/*
+ * This just sets the file->private_data back to the cursor and back.
+ */
+static int dcache_readdir_wrapper(struct file *file, struct dir_context *ctx)
+{
+       struct dentry_list *dlist = file->private_data;
+       int ret;
+
+       file->private_data = dlist->cursor;
+       ret = dcache_readdir(file, ctx);
+       dlist->cursor = file->private_data;
+       file->private_data = dlist;
+       return ret;
 }
 
 /**
@@ -491,6 +577,9 @@ struct dentry *eventfs_create_events_dir(const char *name,
        struct tracefs_inode *ti;
        struct inode *inode;
 
+       if (security_locked_down(LOCKDOWN_TRACEFS))
+               return NULL;
+
        if (IS_ERR(dentry))
                return dentry;
 
@@ -507,7 +596,7 @@ struct dentry *eventfs_create_events_dir(const char *name,
        INIT_LIST_HEAD(&ei->e_top_files);
 
        ti = get_tracefs(inode);
-       ti->flags |= TRACEFS_EVENT_INODE;
+       ti->flags |= TRACEFS_EVENT_INODE | TRACEFS_EVENT_TOP_INODE;
        ti->private = ei;
 
        inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
@@ -538,6 +627,9 @@ struct eventfs_file *eventfs_add_subsystem_dir(const char *name,
        struct eventfs_inode *ei_parent;
        struct eventfs_file *ef;
 
+       if (security_locked_down(LOCKDOWN_TRACEFS))
+               return NULL;
+
        if (!parent)
                return ERR_PTR(-EINVAL);
 
@@ -569,6 +661,9 @@ struct eventfs_file *eventfs_add_dir(const char *name,
 {
        struct eventfs_file *ef;
 
+       if (security_locked_down(LOCKDOWN_TRACEFS))
+               return NULL;
+
        if (!ef_parent)
                return ERR_PTR(-EINVAL);
 
@@ -606,6 +701,9 @@ int eventfs_add_events_file(const char *name, umode_t mode,
        struct eventfs_inode *ei;
        struct eventfs_file *ef;
 
+       if (security_locked_down(LOCKDOWN_TRACEFS))
+               return -ENODEV;
+
        if (!parent)
                return -EINVAL;
 
@@ -654,6 +752,9 @@ int eventfs_add_file(const char *name, umode_t mode,
 {
        struct eventfs_file *ef;
 
+       if (security_locked_down(LOCKDOWN_TRACEFS))
+               return -ENODEV;
+
        if (!ef_parent)
                return -EINVAL;
 
@@ -791,7 +892,6 @@ void eventfs_remove(struct eventfs_file *ef)
 void eventfs_remove_events_dir(struct dentry *dentry)
 {
        struct tracefs_inode *ti;
-       struct eventfs_inode *ei;
 
        if (!dentry || !dentry->d_inode)
                return;
@@ -800,8 +900,6 @@ void eventfs_remove_events_dir(struct dentry *dentry)
        if (!ti || !(ti->flags & TRACEFS_EVENT_INODE))
                return;
 
-       ei = ti->private;
        d_invalidate(dentry);
        dput(dentry);
-       kfree(ei);
 }
index de5b72216b1a706bc825a1cea3471079f73631ca..891653ba9cf35863f5cc83638b2a2a9a88a03444 100644 (file)
@@ -385,7 +385,7 @@ static void tracefs_dentry_iput(struct dentry *dentry, struct inode *inode)
 
        ti = get_tracefs(inode);
        if (ti && ti->flags & TRACEFS_EVENT_INODE)
-               eventfs_set_ef_status_free(dentry);
+               eventfs_set_ef_status_free(ti, dentry);
        iput(inode);
 }
 
@@ -673,6 +673,9 @@ static struct dentry *__create_dir(const char *name, struct dentry *parent,
  */
 struct dentry *tracefs_create_dir(const char *name, struct dentry *parent)
 {
+       if (security_locked_down(LOCKDOWN_TRACEFS))
+               return NULL;
+
        return __create_dir(name, parent, &simple_dir_inode_operations);
 }
 
index 69c2b1d87c464e6998de175c6d94d8f89a2d46a5..4f2e49e2197b14e70dcaf771ea131835e833a6ee 100644 (file)
@@ -3,7 +3,8 @@
 #define _TRACEFS_INTERNAL_H
 
 enum {
-       TRACEFS_EVENT_INODE     = BIT(1),
+       TRACEFS_EVENT_INODE             = BIT(1),
+       TRACEFS_EVENT_TOP_INODE         = BIT(2),
 };
 
 struct tracefs_inode {
@@ -24,6 +25,6 @@ struct inode *tracefs_get_inode(struct super_block *sb);
 struct dentry *eventfs_start_creating(const char *name, struct dentry *parent);
 struct dentry *eventfs_failed_creating(struct dentry *dentry);
 struct dentry *eventfs_end_creating(struct dentry *dentry);
-void eventfs_set_ef_status_free(struct dentry *dentry);
+void eventfs_set_ef_status_free(struct tracefs_inode *ti, struct dentry *dentry);
 
 #endif /* _TRACEFS_INTERNAL_H */
index c9d653168ad03bbe95e9bc738523ec0ae6e676ac..ed0bc8cbc703d9c345f121f1226e13f419b511d4 100644 (file)
@@ -147,7 +147,7 @@ config XFS_ONLINE_SCRUB_STATS
        bool "XFS online metadata check usage data collection"
        default y
        depends on XFS_ONLINE_SCRUB
-       select FS_DEBUG
+       select XFS_DEBUG
        help
          If you say Y here, the kernel will gather usage data about
          the online metadata check subsystem.  This includes the number
index 2420865f300719d8974c316934c4d4013c9f42d9..a5100a11faf9cd26943a21410f6f7c0d9fb34e96 100644 (file)
@@ -131,4 +131,26 @@ void xlog_check_buf_cancel_table(struct xlog *log);
 #define xlog_check_buf_cancel_table(log) do { } while (0)
 #endif
 
+/*
+ * Transform a regular reservation into one suitable for recovery of a log
+ * intent item.
+ *
+ * Intent recovery only runs a single step of the transaction chain and defers
+ * the rest to a separate transaction.  Therefore, we reduce logcount to 1 here
+ * to avoid livelocks if the log grant space is nearly exhausted due to the
+ * recovered intent pinning the tail.  Keep the same logflags to avoid tripping
+ * asserts elsewhere.  Struct copies abound below.
+ */
+static inline struct xfs_trans_res
+xlog_recover_resv(const struct xfs_trans_res *r)
+{
+       struct xfs_trans_res ret = {
+               .tr_logres      = r->tr_logres,
+               .tr_logcount    = 1,
+               .tr_logflags    = r->tr_logflags,
+       };
+
+       return ret;
+}
+
 #endif /* __XFS_LOG_RECOVER_H__ */
index 5e174685a77c5ee4f52984e71530a585bf011aff..6264daaab37b06151bd12abc2ef9f41f61fcc675 100644 (file)
@@ -266,7 +266,8 @@ xfs_validate_sb_write(
                return -EFSCORRUPTED;
        }
 
-       if (xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
+       if (!xfs_is_readonly(mp) &&
+           xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
                xfs_alert(mp,
 "Corruption detected in superblock read-only compatible features (0x%x)!",
                        (sbp->sb_features_ro_compat &
index ad22656376d3f88521f98c2c5d9f573e7cd2aeca..6b2296ff248a4385c737c943064c9234dfef402f 100644 (file)
@@ -62,12 +62,12 @@ xfs_trans_ichgtime(
        ASSERT(tp);
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
-       /* If the mtime changes, then ctime must also change */
-       ASSERT(flags & XFS_ICHGTIME_CHG);
+       tv = current_time(inode);
 
-       tv = inode_set_ctime_current(inode);
        if (flags & XFS_ICHGTIME_MOD)
                inode->i_mtime = tv;
+       if (flags & XFS_ICHGTIME_CHG)
+               inode_set_ctime_to_ts(inode, tv);
        if (flags & XFS_ICHGTIME_CREATE)
                ip->i_crtime = tv;
 }
index 7d3aa14d81b55e9f0b867fb569da2ea11af61375..4849efcaa33aea500372195b1027976e6d2b0e58 100644 (file)
@@ -588,6 +588,8 @@ out_nofix:
 out_teardown:
        error = xchk_teardown(sc, error);
 out_sc:
+       if (error != -ENOENT)
+               xchk_stats_merge(mp, sm, &run);
        kfree(sc);
 out:
        trace_xchk_done(XFS_I(file_inode(file)), sm, error);
@@ -595,8 +597,6 @@ out:
                sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
                error = 0;
        }
-       if (error != -ENOENT)
-               xchk_stats_merge(mp, sm, &run);
        return error;
 need_drain:
        error = xchk_teardown(sc, 0);
index aeb92624176b9d1636ce10f14790efc480544478..cd91db4a554896fdcdd61f4824ae4047cab93017 100644 (file)
@@ -185,7 +185,10 @@ xchk_stats_merge_one(
 {
        struct xchk_scrub_stats         *css;
 
-       ASSERT(sm->sm_type < XFS_SCRUB_TYPE_NR);
+       if (sm->sm_type >= XFS_SCRUB_TYPE_NR) {
+               ASSERT(sm->sm_type < XFS_SCRUB_TYPE_NR);
+               return;
+       }
 
        css = &cs->cs_stats[sm->sm_type];
        spin_lock(&css->css_lock);
index 5db87b34fb6e2067442e50d7e586605978e27b0a..89c7a9f4f93054d20b3504a8192fe16deee0dbda 100644 (file)
@@ -333,7 +333,6 @@ xfs_attr_inactive(
        int                     error = 0;
 
        mp = dp->i_mount;
-       ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
 
        xfs_ilock(dp, lock_mode);
        if (!xfs_inode_has_attr_fork(dp))
index 2788a6f2edcdb82b1765af1a7a939ac2420e8c71..36fe2abb16e6e35563a0f7d5ca8ed895c4ff2130 100644 (file)
@@ -547,7 +547,7 @@ xfs_attri_item_recover(
        struct xfs_inode                *ip;
        struct xfs_da_args              *args;
        struct xfs_trans                *tp;
-       struct xfs_trans_res            tres;
+       struct xfs_trans_res            resv;
        struct xfs_attri_log_format     *attrp;
        struct xfs_attri_log_nameval    *nv = attrip->attri_nameval;
        int                             error;
@@ -618,8 +618,9 @@ xfs_attri_item_recover(
                goto out;
        }
 
-       xfs_init_attr_trans(args, &tres, &total);
-       error = xfs_trans_alloc(mp, &tres, total, 0, XFS_TRANS_RESERVE, &tp);
+       xfs_init_attr_trans(args, &resv, &total);
+       resv = xlog_recover_resv(&resv);
+       error = xfs_trans_alloc(mp, &resv, total, 0, XFS_TRANS_RESERVE, &tp);
        if (error)
                goto out;
 
index 7551c3ec4ea5d68eaba0d233ac7c4446d02614b8..e736a0844c89d655e717fec39f96b939e764dc73 100644 (file)
@@ -490,6 +490,7 @@ xfs_bui_item_recover(
        struct list_head                *capture_list)
 {
        struct xfs_bmap_intent          fake = { };
+       struct xfs_trans_res            resv;
        struct xfs_bui_log_item         *buip = BUI_ITEM(lip);
        struct xfs_trans                *tp;
        struct xfs_inode                *ip = NULL;
@@ -515,7 +516,8 @@ xfs_bui_item_recover(
                return error;
 
        /* Allocate transaction and do the work. */
-       error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
+       resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate);
+       error = xfs_trans_alloc(mp, &resv,
                        XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK), 0, 0, &tp);
        if (error)
                goto err_rele;
index 1064c2342876807837bf400a87ac9d296bfec9fa..f71ea786a6d2256c75742c58998c47d2eb4067fd 100644 (file)
@@ -146,6 +146,12 @@ xfs_nfs_get_inode(
                return ERR_PTR(error);
        }
 
+       error = xfs_inode_reload_unlinked(ip);
+       if (error) {
+               xfs_irele(ip);
+               return ERR_PTR(error);
+       }
+
        if (VFS_I(ip)->i_generation != generation) {
                xfs_irele(ip);
                return ERR_PTR(-ESTALE);
index f1a5ecf099aabf6779a69a85a64b34207c2c8781..3fa8789820ad9d4e5014aa4e00b1e4c3dc3ee874 100644 (file)
@@ -660,6 +660,7 @@ xfs_efi_item_recover(
        struct xfs_log_item             *lip,
        struct list_head                *capture_list)
 {
+       struct xfs_trans_res            resv;
        struct xfs_efi_log_item         *efip = EFI_ITEM(lip);
        struct xfs_mount                *mp = lip->li_log->l_mp;
        struct xfs_efd_log_item         *efdp;
@@ -683,7 +684,8 @@ xfs_efi_item_recover(
                }
        }
 
-       error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
+       resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate);
+       error = xfs_trans_alloc(mp, &resv, 0, 0, 0, &tp);
        if (error)
                return error;
        efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents);
index 10403ba9b58f7d31d42ee2f0a80993f692557beb..736e5545f584025ec204dfc6059e83fc06e99bdb 100644 (file)
@@ -565,6 +565,19 @@ err:
 }
 #endif /* CONFIG_XFS_RT */
 
+static inline bool
+rmap_not_shareable(struct xfs_mount *mp, const struct xfs_rmap_irec *r)
+{
+       if (!xfs_has_reflink(mp))
+               return true;
+       if (XFS_RMAP_NON_INODE_OWNER(r->rm_owner))
+               return true;
+       if (r->rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK |
+                          XFS_RMAP_UNWRITTEN))
+               return true;
+       return false;
+}
+
 /* Execute a getfsmap query against the regular data device. */
 STATIC int
 __xfs_getfsmap_datadev(
@@ -598,7 +611,6 @@ __xfs_getfsmap_datadev(
         * low to the fsmap low key and max out the high key to the end
         * of the AG.
         */
-       info->low.rm_startblock = XFS_FSB_TO_AGBNO(mp, start_fsb);
        info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
        error = xfs_fsmap_owner_to_rmap(&info->low, &keys[0]);
        if (error)
@@ -608,12 +620,9 @@ __xfs_getfsmap_datadev(
 
        /* Adjust the low key if we are continuing from where we left off. */
        if (info->low.rm_blockcount == 0) {
-               /* empty */
-       } else if (XFS_RMAP_NON_INODE_OWNER(info->low.rm_owner) ||
-                  (info->low.rm_flags & (XFS_RMAP_ATTR_FORK |
-                                         XFS_RMAP_BMBT_BLOCK |
-                                         XFS_RMAP_UNWRITTEN))) {
-               info->low.rm_startblock += info->low.rm_blockcount;
+               /* No previous record from which to continue */
+       } else if (rmap_not_shareable(mp, &info->low)) {
+               /* Last record seen was an unshareable extent */
                info->low.rm_owner = 0;
                info->low.rm_offset = 0;
 
@@ -621,8 +630,10 @@ __xfs_getfsmap_datadev(
                if (XFS_FSB_TO_DADDR(mp, start_fsb) >= eofs)
                        return 0;
        } else {
+               /* Last record seen was a shareable file data extent */
                info->low.rm_offset += info->low.rm_blockcount;
        }
+       info->low.rm_startblock = XFS_FSB_TO_AGBNO(mp, start_fsb);
 
        info->high.rm_startblock = -1U;
        info->high.rm_owner = ULLONG_MAX;
index e541f5c0bc251c4a1e2d74b3094e32f30b6ccd94..3c210ac8371368bc00a77fb9df52315b710d17ce 100644 (file)
@@ -113,7 +113,7 @@ xfs_inode_alloc(
        INIT_LIST_HEAD(&ip->i_ioend_list);
        spin_lock_init(&ip->i_ioend_lock);
        ip->i_next_unlinked = NULLAGINO;
-       ip->i_prev_unlinked = NULLAGINO;
+       ip->i_prev_unlinked = 0;
 
        return ip;
 }
@@ -443,7 +443,7 @@ xfs_inodegc_queue_all(
        int                     cpu;
        bool                    ret = false;
 
-       for_each_online_cpu(cpu) {
+       for_each_cpu(cpu, &mp->m_inodegc_cpumask) {
                gc = per_cpu_ptr(mp->m_inodegc, cpu);
                if (!llist_empty(&gc->list)) {
                        mod_delayed_work_on(cpu, mp->m_inodegc_wq, &gc->work, 0);
@@ -463,7 +463,7 @@ xfs_inodegc_wait_all(
        int                     error = 0;
 
        flush_workqueue(mp->m_inodegc_wq);
-       for_each_online_cpu(cpu) {
+       for_each_cpu(cpu, &mp->m_inodegc_cpumask) {
                struct xfs_inodegc      *gc;
 
                gc = per_cpu_ptr(mp->m_inodegc, cpu);
@@ -1845,9 +1845,17 @@ xfs_inodegc_worker(
                                                struct xfs_inodegc, work);
        struct llist_node       *node = llist_del_all(&gc->list);
        struct xfs_inode        *ip, *n;
+       struct xfs_mount        *mp = gc->mp;
        unsigned int            nofs_flag;
 
-       ASSERT(gc->cpu == smp_processor_id());
+       /*
+        * Clear the cpu mask bit and ensure that we have seen the latest
+        * update of the gc structure associated with this CPU. This matches
+        * with the release semantics used when setting the cpumask bit in
+        * xfs_inodegc_queue.
+        */
+       cpumask_clear_cpu(gc->cpu, &mp->m_inodegc_cpumask);
+       smp_mb__after_atomic();
 
        WRITE_ONCE(gc->items, 0);
 
@@ -1862,7 +1870,7 @@ xfs_inodegc_worker(
        nofs_flag = memalloc_nofs_save();
 
        ip = llist_entry(node, struct xfs_inode, i_gclist);
-       trace_xfs_inodegc_worker(ip->i_mount, READ_ONCE(gc->shrinker_hits));
+       trace_xfs_inodegc_worker(mp, READ_ONCE(gc->shrinker_hits));
 
        WRITE_ONCE(gc->shrinker_hits, 0);
        llist_for_each_entry_safe(ip, n, node, i_gclist) {
@@ -2057,6 +2065,7 @@ xfs_inodegc_queue(
        struct xfs_inodegc      *gc;
        int                     items;
        unsigned int            shrinker_hits;
+       unsigned int            cpu_nr;
        unsigned long           queue_delay = 1;
 
        trace_xfs_inode_set_need_inactive(ip);
@@ -2064,18 +2073,28 @@ xfs_inodegc_queue(
        ip->i_flags |= XFS_NEED_INACTIVE;
        spin_unlock(&ip->i_flags_lock);
 
-       gc = get_cpu_ptr(mp->m_inodegc);
+       cpu_nr = get_cpu();
+       gc = this_cpu_ptr(mp->m_inodegc);
        llist_add(&ip->i_gclist, &gc->list);
        items = READ_ONCE(gc->items);
        WRITE_ONCE(gc->items, items + 1);
        shrinker_hits = READ_ONCE(gc->shrinker_hits);
 
+       /*
+        * Ensure the list add is always seen by anyone who finds the cpumask
+        * bit set. This effectively gives the cpumask bit set operation
+        * release ordering semantics.
+        */
+       smp_mb__before_atomic();
+       if (!cpumask_test_cpu(cpu_nr, &mp->m_inodegc_cpumask))
+               cpumask_test_and_set_cpu(cpu_nr, &mp->m_inodegc_cpumask);
+
        /*
         * We queue the work while holding the current CPU so that the work
         * is scheduled to run on this CPU.
         */
        if (!xfs_is_inodegc_enabled(mp)) {
-               put_cpu_ptr(gc);
+               put_cpu();
                return;
        }
 
@@ -2085,7 +2104,7 @@ xfs_inodegc_queue(
        trace_xfs_inodegc_queue(mp, __return_address);
        mod_delayed_work_on(current_cpu(), mp->m_inodegc_wq, &gc->work,
                        queue_delay);
-       put_cpu_ptr(gc);
+       put_cpu();
 
        if (xfs_inodegc_want_flush_work(ip, items, shrinker_hits)) {
                trace_xfs_inodegc_throttle(mp, __return_address);
@@ -2093,47 +2112,6 @@ xfs_inodegc_queue(
        }
 }
 
-/*
- * Fold the dead CPU inodegc queue into the current CPUs queue.
- */
-void
-xfs_inodegc_cpu_dead(
-       struct xfs_mount        *mp,
-       unsigned int            dead_cpu)
-{
-       struct xfs_inodegc      *dead_gc, *gc;
-       struct llist_node       *first, *last;
-       unsigned int            count = 0;
-
-       dead_gc = per_cpu_ptr(mp->m_inodegc, dead_cpu);
-       cancel_delayed_work_sync(&dead_gc->work);
-
-       if (llist_empty(&dead_gc->list))
-               return;
-
-       first = dead_gc->list.first;
-       last = first;
-       while (last->next) {
-               last = last->next;
-               count++;
-       }
-       dead_gc->list.first = NULL;
-       dead_gc->items = 0;
-
-       /* Add pending work to current CPU */
-       gc = get_cpu_ptr(mp->m_inodegc);
-       llist_add_batch(first, last, &gc->list);
-       count += READ_ONCE(gc->items);
-       WRITE_ONCE(gc->items, count);
-
-       if (xfs_is_inodegc_enabled(mp)) {
-               trace_xfs_inodegc_queue(mp, __return_address);
-               mod_delayed_work_on(current_cpu(), mp->m_inodegc_wq, &gc->work,
-                               0);
-       }
-       put_cpu_ptr(gc);
-}
-
 /*
  * We set the inode flag atomically with the radix tree tag.  Once we get tag
  * lookups on the radix tree, this inode flag can go away.
@@ -2195,7 +2173,7 @@ xfs_inodegc_shrinker_count(
        if (!xfs_is_inodegc_enabled(mp))
                return 0;
 
-       for_each_online_cpu(cpu) {
+       for_each_cpu(cpu, &mp->m_inodegc_cpumask) {
                gc = per_cpu_ptr(mp->m_inodegc, cpu);
                if (!llist_empty(&gc->list))
                        return XFS_INODEGC_SHRINKER_COUNT;
@@ -2220,7 +2198,7 @@ xfs_inodegc_shrinker_scan(
 
        trace_xfs_inodegc_shrinker_scan(mp, sc, __return_address);
 
-       for_each_online_cpu(cpu) {
+       for_each_cpu(cpu, &mp->m_inodegc_cpumask) {
                gc = per_cpu_ptr(mp->m_inodegc, cpu);
                if (!llist_empty(&gc->list)) {
                        unsigned int    h = READ_ONCE(gc->shrinker_hits);
index 2fa6f2e09d078a2a884bf1bc88bec960eeea92aa..905944dafbe539245bc30fe2df2d8681af0c5a04 100644 (file)
@@ -79,7 +79,6 @@ void xfs_inodegc_push(struct xfs_mount *mp);
 int xfs_inodegc_flush(struct xfs_mount *mp);
 void xfs_inodegc_stop(struct xfs_mount *mp);
 void xfs_inodegc_start(struct xfs_mount *mp);
-void xfs_inodegc_cpu_dead(struct xfs_mount *mp, unsigned int cpu);
 int xfs_inodegc_register_shrinker(struct xfs_mount *mp);
 
 #endif
index 360fe83a334fc5dcf061d22628bee58d0baa3619..f94f7b3740415067c143bb19cbfb5c5c0dd5f4a1 100644 (file)
@@ -1642,8 +1642,11 @@ xfs_inode_needs_inactive(
        if (VFS_I(ip)->i_mode == 0)
                return false;
 
-       /* If this is a read-only mount, don't do this (would generate I/O) */
-       if (xfs_is_readonly(mp))
+       /*
+        * If this is a read-only mount, don't do this (would generate I/O)
+        * unless we're in log recovery and cleaning the iunlinked list.
+        */
+       if (xfs_is_readonly(mp) && !xlog_recovery_needed(mp->m_log))
                return false;
 
        /* If the log isn't running, push inodes straight to reclaim. */
@@ -1703,8 +1706,11 @@ xfs_inactive(
        mp = ip->i_mount;
        ASSERT(!xfs_iflags_test(ip, XFS_IRECOVERY));
 
-       /* If this is a read-only mount, don't do this (would generate I/O) */
-       if (xfs_is_readonly(mp))
+       /*
+        * If this is a read-only mount, don't do this (would generate I/O)
+        * unless we're in log recovery and cleaning the iunlinked list.
+        */
+       if (xfs_is_readonly(mp) && !xlog_recovery_needed(mp->m_log))
                goto out;
 
        /* Metadata inodes require explicit resource cleanup. */
@@ -1736,9 +1742,13 @@ xfs_inactive(
             ip->i_df.if_nextents > 0 || ip->i_delayed_blks > 0))
                truncate = 1;
 
-       error = xfs_qm_dqattach(ip);
-       if (error)
-               goto out;
+       if (xfs_iflags_test(ip, XFS_IQUOTAUNCHECKED)) {
+               xfs_qm_dqdetach(ip);
+       } else {
+               error = xfs_qm_dqattach(ip);
+               if (error)
+                       goto out;
+       }
 
        if (S_ISLNK(VFS_I(ip)->i_mode))
                error = xfs_inactive_symlink(ip);
@@ -1822,12 +1832,17 @@ xfs_iunlink_lookup(
 
        rcu_read_lock();
        ip = radix_tree_lookup(&pag->pag_ici_root, agino);
+       if (!ip) {
+               /* Caller can handle inode not being in memory. */
+               rcu_read_unlock();
+               return NULL;
+       }
 
        /*
-        * Inode not in memory or in RCU freeing limbo should not happen.
-        * Warn about this and let the caller handle the failure.
+        * Inode in RCU freeing limbo should not happen.  Warn about this and
+        * let the caller handle the failure.
         */
-       if (WARN_ON_ONCE(!ip || !ip->i_ino)) {
+       if (WARN_ON_ONCE(!ip->i_ino)) {
                rcu_read_unlock();
                return NULL;
        }
@@ -1836,7 +1851,10 @@ xfs_iunlink_lookup(
        return ip;
 }
 
-/* Update the prev pointer of the next agino. */
+/*
+ * Update the prev pointer of the next agino.  Returns -ENOLINK if the inode
+ * is not in cache.
+ */
 static int
 xfs_iunlink_update_backref(
        struct xfs_perag        *pag,
@@ -1851,7 +1869,8 @@ xfs_iunlink_update_backref(
 
        ip = xfs_iunlink_lookup(pag, next_agino);
        if (!ip)
-               return -EFSCORRUPTED;
+               return -ENOLINK;
+
        ip->i_prev_unlinked = prev_agino;
        return 0;
 }
@@ -1895,6 +1914,64 @@ xfs_iunlink_update_bucket(
        return 0;
 }
 
+/*
+ * Load the inode @next_agino into the cache and set its prev_unlinked pointer
+ * to @prev_agino.  Caller must hold the AGI to synchronize with other changes
+ * to the unlinked list.
+ */
+STATIC int
+xfs_iunlink_reload_next(
+       struct xfs_trans        *tp,
+       struct xfs_buf          *agibp,
+       xfs_agino_t             prev_agino,
+       xfs_agino_t             next_agino)
+{
+       struct xfs_perag        *pag = agibp->b_pag;
+       struct xfs_mount        *mp = pag->pag_mount;
+       struct xfs_inode        *next_ip = NULL;
+       xfs_ino_t               ino;
+       int                     error;
+
+       ASSERT(next_agino != NULLAGINO);
+
+#ifdef DEBUG
+       rcu_read_lock();
+       next_ip = radix_tree_lookup(&pag->pag_ici_root, next_agino);
+       ASSERT(next_ip == NULL);
+       rcu_read_unlock();
+#endif
+
+       xfs_info_ratelimited(mp,
+ "Found unrecovered unlinked inode 0x%x in AG 0x%x.  Initiating recovery.",
+                       next_agino, pag->pag_agno);
+
+       /*
+        * Use an untrusted lookup just to be cautious in case the AGI has been
+        * corrupted and now points at a free inode.  That shouldn't happen,
+        * but we'd rather shut down now since we're already running in a weird
+        * situation.
+        */
+       ino = XFS_AGINO_TO_INO(mp, pag->pag_agno, next_agino);
+       error = xfs_iget(mp, tp, ino, XFS_IGET_UNTRUSTED, 0, &next_ip);
+       if (error)
+               return error;
+
+       /* If this is not an unlinked inode, something is very wrong. */
+       if (VFS_I(next_ip)->i_nlink != 0) {
+               error = -EFSCORRUPTED;
+               goto rele;
+       }
+
+       next_ip->i_prev_unlinked = prev_agino;
+       trace_xfs_iunlink_reload_next(next_ip);
+rele:
+       ASSERT(!(VFS_I(next_ip)->i_state & I_DONTCACHE));
+       if (xfs_is_quotacheck_running(mp) && next_ip)
+               xfs_iflags_set(next_ip, XFS_IQUOTAUNCHECKED);
+       xfs_irele(next_ip);
+       return error;
+}
+
 static int
 xfs_iunlink_insert_inode(
        struct xfs_trans        *tp,
@@ -1926,6 +2003,8 @@ xfs_iunlink_insert_inode(
         * inode.
         */
        error = xfs_iunlink_update_backref(pag, agino, next_agino);
+       if (error == -ENOLINK)
+               error = xfs_iunlink_reload_next(tp, agibp, agino, next_agino);
        if (error)
                return error;
 
@@ -1941,6 +2020,7 @@ xfs_iunlink_insert_inode(
        }
 
        /* Point the head of the list to point to this inode. */
+       ip->i_prev_unlinked = NULLAGINO;
        return xfs_iunlink_update_bucket(tp, pag, agibp, bucket_index, agino);
 }
 
@@ -2020,6 +2100,9 @@ xfs_iunlink_remove_inode(
         */
        error = xfs_iunlink_update_backref(pag, ip->i_prev_unlinked,
                        ip->i_next_unlinked);
+       if (error == -ENOLINK)
+               error = xfs_iunlink_reload_next(tp, agibp, ip->i_prev_unlinked,
+                               ip->i_next_unlinked);
        if (error)
                return error;
 
@@ -2040,7 +2123,7 @@ xfs_iunlink_remove_inode(
        }
 
        ip->i_next_unlinked = NULLAGINO;
-       ip->i_prev_unlinked = NULLAGINO;
+       ip->i_prev_unlinked = 0;
        return error;
 }
 
@@ -3529,3 +3612,103 @@ xfs_iunlock2_io_mmap(
        if (ip1 != ip2)
                inode_unlock(VFS_I(ip1));
 }
+
+/*
+ * Reload the incore inode list for this inode.  Caller should ensure that
+ * the link count cannot change, either by taking ILOCK_SHARED or otherwise
+ * preventing other threads from executing.
+ */
+int
+xfs_inode_reload_unlinked_bucket(
+       struct xfs_trans        *tp,
+       struct xfs_inode        *ip)
+{
+       struct xfs_mount        *mp = tp->t_mountp;
+       struct xfs_buf          *agibp;
+       struct xfs_agi          *agi;
+       struct xfs_perag        *pag;
+       xfs_agnumber_t          agno = XFS_INO_TO_AGNO(mp, ip->i_ino);
+       xfs_agino_t             agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
+       xfs_agino_t             prev_agino, next_agino;
+       unsigned int            bucket;
+       bool                    foundit = false;
+       int                     error;
+
+       /* Grab the first inode in the list */
+       pag = xfs_perag_get(mp, agno);
+       error = xfs_ialloc_read_agi(pag, tp, &agibp);
+       xfs_perag_put(pag);
+       if (error)
+               return error;
+
+       bucket = agino % XFS_AGI_UNLINKED_BUCKETS;
+       agi = agibp->b_addr;
+
+       trace_xfs_inode_reload_unlinked_bucket(ip);
+
+       xfs_info_ratelimited(mp,
+ "Found unrecovered unlinked inode 0x%x in AG 0x%x.  Initiating list recovery.",
+                       agino, agno);
+
+       prev_agino = NULLAGINO;
+       next_agino = be32_to_cpu(agi->agi_unlinked[bucket]);
+       while (next_agino != NULLAGINO) {
+               struct xfs_inode        *next_ip = NULL;
+
+               if (next_agino == agino) {
+                       /* Found this inode, set its backlink. */
+                       next_ip = ip;
+                       next_ip->i_prev_unlinked = prev_agino;
+                       foundit = true;
+               }
+               if (!next_ip) {
+                       /* Inode already in memory. */
+                       next_ip = xfs_iunlink_lookup(pag, next_agino);
+               }
+               if (!next_ip) {
+                       /* Inode not in memory, reload. */
+                       error = xfs_iunlink_reload_next(tp, agibp, prev_agino,
+                                       next_agino);
+                       if (error)
+                               break;
+
+                       next_ip = xfs_iunlink_lookup(pag, next_agino);
+               }
+               if (!next_ip) {
+                       /* No incore inode at all?  We reloaded it... */
+                       ASSERT(next_ip != NULL);
+                       error = -EFSCORRUPTED;
+                       break;
+               }
+
+               prev_agino = next_agino;
+               next_agino = next_ip->i_next_unlinked;
+       }
+
+       xfs_trans_brelse(tp, agibp);
+       /* Should have found this inode somewhere in the iunlinked bucket. */
+       if (!error && !foundit)
+               error = -EFSCORRUPTED;
+       return error;
+}
+
+/* Decide if this inode is missing its unlinked list and reload it. */
+int
+xfs_inode_reload_unlinked(
+       struct xfs_inode        *ip)
+{
+       struct xfs_trans        *tp;
+       int                     error;
+
+       error = xfs_trans_alloc_empty(ip->i_mount, &tp);
+       if (error)
+               return error;
+
+       xfs_ilock(ip, XFS_ILOCK_SHARED);
+       if (xfs_inode_unlinked_incomplete(ip))
+               error = xfs_inode_reload_unlinked_bucket(tp, ip);
+       xfs_iunlock(ip, XFS_ILOCK_SHARED);
+       xfs_trans_cancel(tp);
+
+       return error;
+}
index 7547caf2f2abd525010aa046d8b1e93e29d599dd..0c5bdb91152e1cf920cfb5cb76268d0b025640fc 100644 (file)
@@ -68,8 +68,21 @@ typedef struct xfs_inode {
        uint64_t                i_diflags2;     /* XFS_DIFLAG2_... */
        struct timespec64       i_crtime;       /* time created */
 
-       /* unlinked list pointers */
+       /*
+        * Unlinked list pointers.  These point to the next and previous inodes
+        * in the AGI unlinked bucket list, respectively.  These fields can
+        * only be updated with the AGI locked.
+        *
+        * i_next_unlinked caches di_next_unlinked.
+        */
        xfs_agino_t             i_next_unlinked;
+
+       /*
+        * If the inode is not on an unlinked list, this field is zero.  If the
+        * inode is the first element in an unlinked list, this field is
+        * NULLAGINO.  Otherwise, i_prev_unlinked points to the previous inode
+        * in the unlinked list.
+        */
        xfs_agino_t             i_prev_unlinked;
 
        /* VFS inode */
@@ -81,6 +94,11 @@ typedef struct xfs_inode {
        struct list_head        i_ioend_list;
 } xfs_inode_t;
 
+static inline bool xfs_inode_on_unlinked_list(const struct xfs_inode *ip)
+{
+       return ip->i_prev_unlinked != 0;
+}
+
 static inline bool xfs_inode_has_attr_fork(struct xfs_inode *ip)
 {
        return ip->i_forkoff > 0;
@@ -326,6 +344,9 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip)
  */
 #define XFS_INACTIVATING       (1 << 13)
 
+/* Quotacheck is running but inode has not been added to quota counts. */
+#define XFS_IQUOTAUNCHECKED    (1 << 14)
+
 /* All inode state flags related to inode reclaim. */
 #define XFS_ALL_IRECLAIM_FLAGS (XFS_IRECLAIMABLE | \
                                 XFS_IRECLAIM | \
@@ -340,7 +361,7 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip)
 #define XFS_IRECLAIM_RESET_FLAGS       \
        (XFS_IRECLAIMABLE | XFS_IRECLAIM | \
         XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | XFS_NEED_INACTIVE | \
-        XFS_INACTIVATING)
+        XFS_INACTIVATING | XFS_IQUOTAUNCHECKED)
 
 /*
  * Flags for inode locking.
@@ -575,4 +596,13 @@ void xfs_end_io(struct work_struct *work);
 int xfs_ilock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2);
 void xfs_iunlock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2);
 
+static inline bool
+xfs_inode_unlinked_incomplete(
+       struct xfs_inode        *ip)
+{
+       return VFS_I(ip)->i_nlink == 0 && !xfs_inode_on_unlinked_list(ip);
+}
+int xfs_inode_reload_unlinked_bucket(struct xfs_trans *tp, struct xfs_inode *ip);
+int xfs_inode_reload_unlinked(struct xfs_inode *ip);
+
 #endif /* __XFS_INODE_H__ */
index 2ededd3f6b8ce861489a54038fa4d700637c845c..1c1e6171209def64e5bafb0d06c0906eff60344d 100644 (file)
@@ -573,10 +573,10 @@ xfs_vn_getattr(
        stat->gid = vfsgid_into_kgid(vfsgid);
        stat->ino = ip->i_ino;
        stat->atime = inode->i_atime;
+       stat->mtime = inode->i_mtime;
+       stat->ctime = inode_get_ctime(inode);
        stat->blocks = XFS_FSB_TO_BB(mp, ip->i_nblocks + ip->i_delayed_blks);
 
-       fill_mg_cmtime(stat, request_mask, inode);
-
        if (xfs_has_v3inodes(mp)) {
                if (request_mask & STATX_BTIME) {
                        stat->result_mask |= STATX_BTIME;
@@ -917,7 +917,7 @@ xfs_setattr_size(
        if (newsize != oldsize &&
            !(iattr->ia_valid & (ATTR_CTIME | ATTR_MTIME))) {
                iattr->ia_ctime = iattr->ia_mtime =
-                       current_mgtime(inode);
+                       current_time(inode);
                iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME;
        }
 
index c2093cb56092bedb2058e3fdd9df13cbd099068b..ccf0c4ff449014b7811ae2b4114cafa208fdf3f5 100644 (file)
@@ -80,6 +80,15 @@ xfs_bulkstat_one_int(
        if (error)
                goto out;
 
+       if (xfs_inode_unlinked_incomplete(ip)) {
+               error = xfs_inode_reload_unlinked_bucket(tp, ip);
+               if (error) {
+                       xfs_iunlock(ip, XFS_ILOCK_SHARED);
+                       xfs_irele(ip);
+                       return error;
+               }
+       }
+
        ASSERT(ip != NULL);
        ASSERT(ip->i_imap.im_blkno != 0);
        inode = VFS_I(ip);
index 79004d193e54dc2b06c796cef994d0bb1ba786eb..51c100c861770f619776a8e3efb921d0b2e55bd8 100644 (file)
@@ -715,15 +715,7 @@ xfs_log_mount(
         * just worked.
         */
        if (!xfs_has_norecovery(mp)) {
-               /*
-                * log recovery ignores readonly state and so we need to clear
-                * mount-based read only state so it can write to disk.
-                */
-               bool    readonly = test_and_clear_bit(XFS_OPSTATE_READONLY,
-                                               &mp->m_opstate);
                error = xlog_recover(log);
-               if (readonly)
-                       set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
                if (error) {
                        xfs_warn(mp, "log mount/recovery failed: error %d",
                                error);
@@ -772,7 +764,6 @@ xfs_log_mount_finish(
        struct xfs_mount        *mp)
 {
        struct xlog             *log = mp->m_log;
-       bool                    readonly;
        int                     error = 0;
 
        if (xfs_has_norecovery(mp)) {
@@ -780,12 +771,6 @@ xfs_log_mount_finish(
                return 0;
        }
 
-       /*
-        * log recovery ignores readonly state and so we need to clear
-        * mount-based read only state so it can write to disk.
-        */
-       readonly = test_and_clear_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
-
        /*
         * During the second phase of log recovery, we need iget and
         * iput to behave like they do for an active filesystem.
@@ -835,8 +820,6 @@ xfs_log_mount_finish(
        xfs_buftarg_drain(mp->m_ddev_targp);
 
        clear_bit(XLOG_RECOVERY_NEEDED, &log->l_opstate);
-       if (readonly)
-               set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
 
        /* Make sure the log is dead if we're returning failure. */
        ASSERT(!error || xlog_is_shutdown(log));
index eccbfb99e89486cca1f1f185d2875d9421d44764..ebc70aaa299c0afc32d7bebd68f4b3c602a849e1 100644 (file)
@@ -124,7 +124,7 @@ xlog_cil_push_pcp_aggregate(
        struct xlog_cil_pcp     *cilpcp;
        int                     cpu;
 
-       for_each_online_cpu(cpu) {
+       for_each_cpu(cpu, &ctx->cil_pcpmask) {
                cilpcp = per_cpu_ptr(cil->xc_pcp, cpu);
 
                ctx->ticket->t_curr_res += cilpcp->space_reserved;
@@ -165,7 +165,13 @@ xlog_cil_insert_pcp_aggregate(
        if (!test_and_clear_bit(XLOG_CIL_PCP_SPACE, &cil->xc_flags))
                return;
 
-       for_each_online_cpu(cpu) {
+       /*
+        * We can race with other cpus setting cil_pcpmask.  However, we've
+        * atomically cleared PCP_SPACE which forces other threads to add to
+        * the global space used count.  cil_pcpmask is a superset of cilpcp
+        * structures that could have a nonzero space_used.
+        */
+       for_each_cpu(cpu, &ctx->cil_pcpmask) {
                int     old, prev;
 
                cilpcp = per_cpu_ptr(cil->xc_pcp, cpu);
@@ -554,6 +560,7 @@ xlog_cil_insert_items(
        int                     iovhdr_res = 0, split_res = 0, ctx_res = 0;
        int                     space_used;
        int                     order;
+       unsigned int            cpu_nr;
        struct xlog_cil_pcp     *cilpcp;
 
        ASSERT(tp);
@@ -577,7 +584,12 @@ xlog_cil_insert_items(
         * can't be scheduled away between split sample/update operations that
         * are done without outside locking to serialise them.
         */
-       cilpcp = get_cpu_ptr(cil->xc_pcp);
+       cpu_nr = get_cpu();
+       cilpcp = this_cpu_ptr(cil->xc_pcp);
+
+       /* Tell the future push that there was work added by this CPU. */
+       if (!cpumask_test_cpu(cpu_nr, &ctx->cil_pcpmask))
+               cpumask_test_and_set_cpu(cpu_nr, &ctx->cil_pcpmask);
 
        /*
         * We need to take the CIL checkpoint unit reservation on the first
@@ -663,7 +675,7 @@ xlog_cil_insert_items(
                        continue;
                list_add_tail(&lip->li_cil, &cilpcp->log_items);
        }
-       put_cpu_ptr(cilpcp);
+       put_cpu();
 
        /*
         * If we've overrun the reservation, dump the tx details before we move
@@ -1790,38 +1802,6 @@ out_shutdown:
        return 0;
 }
 
-/*
- * Move dead percpu state to the relevant CIL context structures.
- *
- * We have to lock the CIL context here to ensure that nothing is modifying
- * the percpu state, either addition or removal. Both of these are done under
- * the CIL context lock, so grabbing that exclusively here will ensure we can
- * safely drain the cilpcp for the CPU that is dying.
- */
-void
-xlog_cil_pcp_dead(
-       struct xlog             *log,
-       unsigned int            cpu)
-{
-       struct xfs_cil          *cil = log->l_cilp;
-       struct xlog_cil_pcp     *cilpcp = per_cpu_ptr(cil->xc_pcp, cpu);
-       struct xfs_cil_ctx      *ctx;
-
-       down_write(&cil->xc_ctx_lock);
-       ctx = cil->xc_ctx;
-       if (ctx->ticket)
-               ctx->ticket->t_curr_res += cilpcp->space_reserved;
-       cilpcp->space_reserved = 0;
-
-       if (!list_empty(&cilpcp->log_items))
-               list_splice_init(&cilpcp->log_items, &ctx->log_items);
-       if (!list_empty(&cilpcp->busy_extents))
-               list_splice_init(&cilpcp->busy_extents, &ctx->busy_extents);
-       atomic_add(cilpcp->space_used, &ctx->space_used);
-       cilpcp->space_used = 0;
-       up_write(&cil->xc_ctx_lock);
-}
-
 /*
  * Perform initial CIL structure initialisation.
  */
index 1bd2963e8fbd10c0adcc02887382030e79ff37ae..af87648331d5df59398eecc636ac820896d1110e 100644 (file)
@@ -231,6 +231,12 @@ struct xfs_cil_ctx {
        struct work_struct      discard_endio_work;
        struct work_struct      push_work;
        atomic_t                order_id;
+
+       /*
+        * CPUs that could have added items to the percpu CIL data.  Access is
+        * coordinated with xc_ctx_lock.
+        */
+       struct cpumask          cil_pcpmask;
 };
 
 /*
@@ -278,9 +284,6 @@ struct xfs_cil {
        wait_queue_head_t       xc_push_wait;   /* background push throttle */
 
        void __percpu           *xc_pcp;        /* percpu CIL structures */
-#ifdef CONFIG_HOTPLUG_CPU
-       struct list_head        xc_pcp_list;
-#endif
 } ____cacheline_aligned_in_smp;
 
 /* xc_flags bit values */
@@ -705,9 +708,4 @@ xlog_kvmalloc(
        return p;
 }
 
-/*
- * CIL CPU dead notifier
- */
-void xlog_cil_pcp_dead(struct xlog *log, unsigned int cpu);
-
 #endif /* __XFS_LOG_PRIV_H__ */
index 82c81d20459d147ce6f18574037b2850863d0176..13b94d2e605bd9ddb852f76eeeea0bd956a595e0 100644 (file)
@@ -329,7 +329,7 @@ xlog_find_verify_cycle(
         * try a smaller size.  We need to be able to read at least
         * a log sector, or we're out of luck.
         */
-       bufblks = 1 << ffs(nbblks);
+       bufblks = roundup_pow_of_two(nbblks);
        while (bufblks > log->l_logBBsize)
                bufblks >>= 1;
        while (!(buffer = xlog_alloc_buffer(log, bufblks))) {
@@ -1528,7 +1528,7 @@ xlog_write_log_records(
         * a smaller size.  We need to be able to write at least a
         * log sector, or we're out of luck.
         */
-       bufblks = 1 << ffs(blocks);
+       bufblks = roundup_pow_of_two(blocks);
        while (bufblks > log->l_logBBsize)
                bufblks >>= 1;
        while (!(buffer = xlog_alloc_buffer(log, bufblks))) {
index a25eece3be2b9b53c1370c112957011046310d7a..d19cca099bc3a701786c3e5e9871f086ac3f290c 100644 (file)
@@ -60,6 +60,7 @@ struct xfs_error_cfg {
  * Per-cpu deferred inode inactivation GC lists.
  */
 struct xfs_inodegc {
+       struct xfs_mount        *mp;
        struct llist_head       list;
        struct delayed_work     work;
        int                     error;
@@ -67,9 +68,7 @@ struct xfs_inodegc {
        /* approximate count of inodes in the list */
        unsigned int            items;
        unsigned int            shrinker_hits;
-#if defined(DEBUG) || defined(XFS_WARN)
        unsigned int            cpu;
-#endif
 };
 
 /*
@@ -98,7 +97,6 @@ typedef struct xfs_mount {
        xfs_buftarg_t           *m_ddev_targp;  /* saves taking the address */
        xfs_buftarg_t           *m_logdev_targp;/* ptr to log device */
        xfs_buftarg_t           *m_rtdev_targp; /* ptr to rt device */
-       struct list_head        m_mount_list;   /* global mount list */
        void __percpu           *m_inodegc;     /* percpu inodegc structures */
 
        /*
@@ -249,6 +247,9 @@ typedef struct xfs_mount {
        unsigned int            *m_errortag;
        struct xfs_kobj         m_errortag_kobj;
 #endif
+
+       /* cpus that have inodes queued for inactivation */
+       struct cpumask          m_inodegc_cpumask;
 } xfs_mount_t;
 
 #define M_IGEO(mp)             (&(mp)->m_ino_geo)
@@ -404,6 +405,8 @@ __XFS_HAS_FEAT(nouuid, NOUUID)
 #define XFS_OPSTATE_WARNED_SHRINK      8
 /* Kernel has logged a warning about logged xattr updates being used. */
 #define XFS_OPSTATE_WARNED_LARP                9
+/* Mount time quotacheck is running */
+#define XFS_OPSTATE_QUOTACHECK_RUNNING 10
 
 #define __XFS_IS_OPSTATE(name, NAME) \
 static inline bool xfs_is_ ## name (struct xfs_mount *mp) \
@@ -426,6 +429,11 @@ __XFS_IS_OPSTATE(inode32, INODE32)
 __XFS_IS_OPSTATE(readonly, READONLY)
 __XFS_IS_OPSTATE(inodegc_enabled, INODEGC_ENABLED)
 __XFS_IS_OPSTATE(blockgc_enabled, BLOCKGC_ENABLED)
+#ifdef CONFIG_XFS_QUOTA
+__XFS_IS_OPSTATE(quotacheck_running, QUOTACHECK_RUNNING)
+#else
+# define xfs_is_quotacheck_running(mp) (false)
+#endif
 
 static inline bool
 xfs_should_warn(struct xfs_mount *mp, long nr)
@@ -443,7 +451,8 @@ xfs_should_warn(struct xfs_mount *mp, long nr)
        { (1UL << XFS_OPSTATE_BLOCKGC_ENABLED),         "blockgc" }, \
        { (1UL << XFS_OPSTATE_WARNED_SCRUB),            "wscrub" }, \
        { (1UL << XFS_OPSTATE_WARNED_SHRINK),           "wshrink" }, \
-       { (1UL << XFS_OPSTATE_WARNED_LARP),             "wlarp" }
+       { (1UL << XFS_OPSTATE_WARNED_LARP),             "wlarp" }, \
+       { (1UL << XFS_OPSTATE_QUOTACHECK_RUNNING),      "quotacheck" }
 
 /*
  * Max and min values for mount-option defined I/O
index 6abcc34fafd8c2e807784908be3004c7e58ffda4..7256090c3895f40ba95a845721abc72307fdc2a4 100644 (file)
@@ -1160,6 +1160,10 @@ xfs_qm_dqusage_adjust(
        if (error)
                return error;
 
+       error = xfs_inode_reload_unlinked(ip);
+       if (error)
+               goto error0;
+
        ASSERT(ip->i_delayed_blks == 0);
 
        if (XFS_IS_REALTIME_INODE(ip)) {
@@ -1173,6 +1177,7 @@ xfs_qm_dqusage_adjust(
        }
 
        nblks = (xfs_qcnt_t)ip->i_nblocks - rtblks;
+       xfs_iflags_clear(ip, XFS_IQUOTAUNCHECKED);
 
        /*
         * Add the (disk blocks and inode) resources occupied by this
@@ -1319,8 +1324,10 @@ xfs_qm_quotacheck(
                flags |= XFS_PQUOTA_CHKD;
        }
 
+       xfs_set_quotacheck_running(mp);
        error = xfs_iwalk_threaded(mp, 0, 0, xfs_qm_dqusage_adjust, 0, true,
                        NULL);
+       xfs_clear_quotacheck_running(mp);
 
        /*
         * On error, the inode walk may have partially populated the dquot
index edd8587658d5577a6c7a8d37a292808ebac94b55..2d4444d61e98766e0b49f1187634b470f66334c9 100644 (file)
@@ -477,6 +477,7 @@ xfs_cui_item_recover(
        struct xfs_log_item             *lip,
        struct list_head                *capture_list)
 {
+       struct xfs_trans_res            resv;
        struct xfs_cui_log_item         *cuip = CUI_ITEM(lip);
        struct xfs_cud_log_item         *cudp;
        struct xfs_trans                *tp;
@@ -514,8 +515,9 @@ xfs_cui_item_recover(
         * doesn't fit.  We need to reserve enough blocks to handle a
         * full btree split on either end of the refcount range.
         */
-       error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
-                       mp->m_refc_maxlevels * 2, 0, XFS_TRANS_RESERVE, &tp);
+       resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate);
+       error = xfs_trans_alloc(mp, &resv, mp->m_refc_maxlevels * 2, 0,
+                       XFS_TRANS_RESERVE, &tp);
        if (error)
                return error;
 
index 520c7ebdfed8d1ab2b1b91a5e45dba19b2ac4907..0e0e747028da2e8638114b3268ee87490eed5f97 100644 (file)
@@ -507,6 +507,7 @@ xfs_rui_item_recover(
        struct xfs_log_item             *lip,
        struct list_head                *capture_list)
 {
+       struct xfs_trans_res            resv;
        struct xfs_rui_log_item         *ruip = RUI_ITEM(lip);
        struct xfs_rud_log_item         *rudp;
        struct xfs_trans                *tp;
@@ -530,8 +531,9 @@ xfs_rui_item_recover(
                }
        }
 
-       error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
-                       mp->m_rmap_maxlevels, 0, XFS_TRANS_RESERVE, &tp);
+       resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate);
+       error = xfs_trans_alloc(mp, &resv, mp->m_rmap_maxlevels, 0,
+                       XFS_TRANS_RESERVE, &tp);
        if (error)
                return error;
        rudp = xfs_trans_get_rud(tp, ruip);
index 1f77014c6e1abd136753807d37ac5cdf12099b76..819a3568b28f46fa9036d888ca0b8284d5f8fed0 100644 (file)
@@ -56,28 +56,6 @@ static struct kset *xfs_kset;                /* top-level xfs sysfs dir */
 static struct xfs_kobj xfs_dbg_kobj;   /* global debug sysfs attrs */
 #endif
 
-#ifdef CONFIG_HOTPLUG_CPU
-static LIST_HEAD(xfs_mount_list);
-static DEFINE_SPINLOCK(xfs_mount_list_lock);
-
-static inline void xfs_mount_list_add(struct xfs_mount *mp)
-{
-       spin_lock(&xfs_mount_list_lock);
-       list_add(&mp->m_mount_list, &xfs_mount_list);
-       spin_unlock(&xfs_mount_list_lock);
-}
-
-static inline void xfs_mount_list_del(struct xfs_mount *mp)
-{
-       spin_lock(&xfs_mount_list_lock);
-       list_del(&mp->m_mount_list);
-       spin_unlock(&xfs_mount_list_lock);
-}
-#else /* !CONFIG_HOTPLUG_CPU */
-static inline void xfs_mount_list_add(struct xfs_mount *mp) {}
-static inline void xfs_mount_list_del(struct xfs_mount *mp) {}
-#endif
-
 enum xfs_dax_mode {
        XFS_DAX_INODE = 0,
        XFS_DAX_ALWAYS = 1,
@@ -1135,9 +1113,8 @@ xfs_inodegc_init_percpu(
 
        for_each_possible_cpu(cpu) {
                gc = per_cpu_ptr(mp->m_inodegc, cpu);
-#if defined(DEBUG) || defined(XFS_WARN)
                gc->cpu = cpu;
-#endif
+               gc->mp = mp;
                init_llist_head(&gc->list);
                gc->items = 0;
                gc->error = 0;
@@ -1168,7 +1145,6 @@ xfs_fs_put_super(
        xfs_freesb(mp);
        xchk_mount_stats_free(mp);
        free_percpu(mp->m_stats.xs_stats);
-       xfs_mount_list_del(mp);
        xfs_inodegc_free_percpu(mp);
        xfs_destroy_percpu_counters(mp);
        xfs_destroy_mount_workqueues(mp);
@@ -1577,13 +1553,6 @@ xfs_fs_fill_super(
        if (error)
                goto out_destroy_counters;
 
-       /*
-        * All percpu data structures requiring cleanup when a cpu goes offline
-        * must be allocated before adding this @mp to the cpu-dead handler's
-        * mount list.
-        */
-       xfs_mount_list_add(mp);
-
        /* Allocate stats memory before we do operations that might use it */
        mp->m_stats.xs_stats = alloc_percpu(struct xfsstats);
        if (!mp->m_stats.xs_stats) {
@@ -1781,7 +1750,6 @@ xfs_fs_fill_super(
  out_free_stats:
        free_percpu(mp->m_stats.xs_stats);
  out_destroy_inodegc:
-       xfs_mount_list_del(mp);
        xfs_inodegc_free_percpu(mp);
  out_destroy_counters:
        xfs_destroy_percpu_counters(mp);
@@ -2065,7 +2033,7 @@ static struct file_system_type xfs_fs_type = {
        .init_fs_context        = xfs_init_fs_context,
        .parameters             = xfs_fs_parameters,
        .kill_sb                = xfs_kill_sb,
-       .fs_flags               = FS_REQUIRES_DEV | FS_ALLOW_IDMAP | FS_MGTIME,
+       .fs_flags               = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
 };
 MODULE_ALIAS_FS("xfs");
 
@@ -2326,49 +2294,6 @@ xfs_destroy_workqueues(void)
        destroy_workqueue(xfs_alloc_wq);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-static int
-xfs_cpu_dead(
-       unsigned int            cpu)
-{
-       struct xfs_mount        *mp, *n;
-
-       spin_lock(&xfs_mount_list_lock);
-       list_for_each_entry_safe(mp, n, &xfs_mount_list, m_mount_list) {
-               spin_unlock(&xfs_mount_list_lock);
-               xfs_inodegc_cpu_dead(mp, cpu);
-               xlog_cil_pcp_dead(mp->m_log, cpu);
-               spin_lock(&xfs_mount_list_lock);
-       }
-       spin_unlock(&xfs_mount_list_lock);
-       return 0;
-}
-
-static int __init
-xfs_cpu_hotplug_init(void)
-{
-       int     error;
-
-       error = cpuhp_setup_state_nocalls(CPUHP_XFS_DEAD, "xfs:dead", NULL,
-                       xfs_cpu_dead);
-       if (error < 0)
-               xfs_alert(NULL,
-"Failed to initialise CPU hotplug, error %d. XFS is non-functional.",
-                       error);
-       return error;
-}
-
-static void
-xfs_cpu_hotplug_destroy(void)
-{
-       cpuhp_remove_state_nocalls(CPUHP_XFS_DEAD);
-}
-
-#else /* !CONFIG_HOTPLUG_CPU */
-static inline int xfs_cpu_hotplug_init(void) { return 0; }
-static inline void xfs_cpu_hotplug_destroy(void) {}
-#endif
-
 STATIC int __init
 init_xfs_fs(void)
 {
@@ -2385,13 +2310,9 @@ init_xfs_fs(void)
 
        xfs_dir_startup();
 
-       error = xfs_cpu_hotplug_init();
-       if (error)
-               goto out;
-
        error = xfs_init_caches();
        if (error)
-               goto out_destroy_hp;
+               goto out;
 
        error = xfs_init_workqueues();
        if (error)
@@ -2475,8 +2396,6 @@ init_xfs_fs(void)
        xfs_destroy_workqueues();
  out_destroy_caches:
        xfs_destroy_caches();
- out_destroy_hp:
-       xfs_cpu_hotplug_destroy();
  out:
        return error;
 }
@@ -2500,7 +2419,6 @@ exit_xfs_fs(void)
        xfs_destroy_workqueues();
        xfs_destroy_caches();
        xfs_uuid_table_free();
-       xfs_cpu_hotplug_destroy();
 }
 
 module_init(init_xfs_fs);
index 902c7f67a117f4831016d093773d73e5297e9a98..3926cf7f2a6ed189ccbf2d76f7b8e02db9e02294 100644 (file)
@@ -3824,6 +3824,51 @@ TRACE_EVENT(xfs_iunlink_update_dinode,
                  __entry->new_ptr)
 );
 
+TRACE_EVENT(xfs_iunlink_reload_next,
+       TP_PROTO(struct xfs_inode *ip),
+       TP_ARGS(ip),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_agnumber_t, agno)
+               __field(xfs_agino_t, agino)
+               __field(xfs_agino_t, prev_agino)
+               __field(xfs_agino_t, next_agino)
+       ),
+       TP_fast_assign(
+               __entry->dev = ip->i_mount->m_super->s_dev;
+               __entry->agno = XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino);
+               __entry->agino = XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino);
+               __entry->prev_agino = ip->i_prev_unlinked;
+               __entry->next_agino = ip->i_next_unlinked;
+       ),
+       TP_printk("dev %d:%d agno 0x%x agino 0x%x prev_unlinked 0x%x next_unlinked 0x%x",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->agno,
+                 __entry->agino,
+                 __entry->prev_agino,
+                 __entry->next_agino)
+);
+
+TRACE_EVENT(xfs_inode_reload_unlinked_bucket,
+       TP_PROTO(struct xfs_inode *ip),
+       TP_ARGS(ip),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_agnumber_t, agno)
+               __field(xfs_agino_t, agino)
+       ),
+       TP_fast_assign(
+               __entry->dev = ip->i_mount->m_super->s_dev;
+               __entry->agno = XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino);
+               __entry->agino = XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino);
+       ),
+       TP_printk("dev %d:%d agno 0x%x agino 0x%x bucket %u",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->agno,
+                 __entry->agino,
+                 __entry->agino % XFS_AGI_UNLINKED_BUCKETS)
+);
+
 DECLARE_EVENT_CLASS(xfs_ag_inode_class,
        TP_PROTO(struct xfs_inode *ip),
        TP_ARGS(ip),
index 43e5c219aaed568ffb5a711b4583b2cdf1723d9c..a3975f325f4ea83dde12540f7d854ab384d4fd4c 100644 (file)
@@ -46,6 +46,17 @@ xfs_attr_grab_log_assist(
        if (xfs_sb_version_haslogxattrs(&mp->m_sb))
                return 0;
 
+       /*
+        * Check if the filesystem featureset is new enough to set this log
+        * incompat feature bit.  Strictly speaking, the minimum requirement is
+        * a V5 filesystem for the superblock field, but we'll require rmap
+        * or reflink to avoid having to deal with really old kernels.
+        */
+       if (!xfs_has_reflink(mp) && !xfs_has_rmapbt(mp)) {
+               error = -EOPNOTSUPP;
+               goto drop_incompat;
+       }
+
        /* Enable log-assisted xattrs. */
        error = xfs_add_incompat_log_feature(mp,
                        XFS_SB_FEAT_INCOMPAT_LOG_XATTRS);
index e0462361adf9ede869e4adea49dc8ad24c41094e..b5bf0b6da791c14c68062e9fb755643ac4db1c54 100644 (file)
@@ -51,6 +51,20 @@ struct drm_exec {
        struct drm_gem_object *prelocked;
 };
 
+/**
+ * drm_exec_obj() - Return the object for a give drm_exec index
+ * @exec: Pointer to the drm_exec context
+ * @index: The index.
+ *
+ * Return: Pointer to the locked object corresponding to @index if
+ * index is within the number of locked objects. NULL otherwise.
+ */
+static inline struct drm_gem_object *
+drm_exec_obj(struct drm_exec *exec, unsigned long index)
+{
+       return index < exec->num_objects ? exec->objects[index] : NULL;
+}
+
 /**
  * drm_exec_for_each_locked_object - iterate over all the locked objects
  * @exec: drm_exec object
@@ -59,10 +73,23 @@ struct drm_exec {
  *
  * Iterate over all the locked GEM objects inside the drm_exec object.
  */
-#define drm_exec_for_each_locked_object(exec, index, obj)      \
-       for (index = 0, obj = (exec)->objects[0];               \
-            index < (exec)->num_objects;                       \
-            ++index, obj = (exec)->objects[index])
+#define drm_exec_for_each_locked_object(exec, index, obj)              \
+       for ((index) = 0; ((obj) = drm_exec_obj(exec, index)); ++(index))
+
+/**
+ * drm_exec_for_each_locked_object_reverse - iterate over all the locked
+ * objects in reverse locking order
+ * @exec: drm_exec object
+ * @index: unsigned long index for the iteration
+ * @obj: the current GEM object
+ *
+ * Iterate over all the locked GEM objects inside the drm_exec object in
+ * reverse locking order. Note that @index may go below zero and wrap,
+ * but that will be caught by drm_exec_obj(), returning a NULL object.
+ */
+#define drm_exec_for_each_locked_object_reverse(exec, index, obj)      \
+       for ((index) = (exec)->num_objects - 1;                         \
+            ((obj) = drm_exec_obj(exec, index)); --(index))
 
 /**
  * drm_exec_until_all_locked - loop until all GEM objects are locked
index 514c8a7a32f0f03d043cee7f16c9391752187795..ba483c87f0e7bd049b056c029b231e62ca535843 100644 (file)
@@ -3,6 +3,8 @@
 #ifndef DRM_KUNIT_HELPERS_H_
 #define DRM_KUNIT_HELPERS_H_
 
+#include <linux/device.h>
+
 #include <kunit/test.h>
 
 struct drm_device;
@@ -51,7 +53,7 @@ __drm_kunit_helper_alloc_drm_device(struct kunit *test,
 {
        struct drm_driver *driver;
 
-       driver = kunit_kzalloc(test, sizeof(*driver), GFP_KERNEL);
+       driver = devm_kzalloc(dev, sizeof(*driver), GFP_KERNEL);
        KUNIT_ASSERT_NOT_NULL(test, driver);
 
        driver->driver_features = features;
index 2dd175f5debd080f4cc20f7090b2ad57ce03df33..29cc10220952dbe05497875b64cd19f00a81362b 100644 (file)
@@ -42,11 +42,13 @@ struct aer_capability_regs {
 
 #if defined(CONFIG_PCIEAER)
 int pci_aer_clear_nonfatal_status(struct pci_dev *dev);
+int pcie_aer_is_native(struct pci_dev *dev);
 #else
 static inline int pci_aer_clear_nonfatal_status(struct pci_dev *dev)
 {
        return -EINVAL;
 }
+static inline int pcie_aer_is_native(struct pci_dev *dev) { return 0; }
 #endif
 
 void cper_print_aer(struct pci_dev *dev, int aer_severity,
index 7c67c17321d4ca4e221045d172b6a62e989a0e27..083f8565371616269fa0050036ec8a3631c44357 100644 (file)
@@ -67,6 +67,8 @@
 #define ARM_SMCCC_VERSION_1_3          0x10003
 
 #define ARM_SMCCC_1_3_SVE_HINT         0x10000
+#define ARM_SMCCC_CALL_HINTS           ARM_SMCCC_1_3_SVE_HINT
+
 
 #define ARM_SMCCC_VERSION_FUNC_ID                                      \
        ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,                         \
index 18f5744dfb5d89f09ff3191bdfc517a0839580d6..b83ef19da13de210e3ae8ce42f8dc022b51d8ef1 100644 (file)
@@ -459,8 +459,6 @@ raw_atomic_read_acquire(const atomic_t *v)
 {
 #if defined(arch_atomic_read_acquire)
        return arch_atomic_read_acquire(v);
-#elif defined(arch_atomic_read)
-       return arch_atomic_read(v);
 #else
        int ret;
 
@@ -508,8 +506,6 @@ raw_atomic_set_release(atomic_t *v, int i)
 {
 #if defined(arch_atomic_set_release)
        arch_atomic_set_release(v, i);
-#elif defined(arch_atomic_set)
-       arch_atomic_set(v, i);
 #else
        if (__native_word(atomic_t)) {
                smp_store_release(&(v)->counter, i);
@@ -2575,8 +2571,6 @@ raw_atomic64_read_acquire(const atomic64_t *v)
 {
 #if defined(arch_atomic64_read_acquire)
        return arch_atomic64_read_acquire(v);
-#elif defined(arch_atomic64_read)
-       return arch_atomic64_read(v);
 #else
        s64 ret;
 
@@ -2624,8 +2618,6 @@ raw_atomic64_set_release(atomic64_t *v, s64 i)
 {
 #if defined(arch_atomic64_set_release)
        arch_atomic64_set_release(v, i);
-#elif defined(arch_atomic64_set)
-       arch_atomic64_set(v, i);
 #else
        if (__native_word(atomic64_t)) {
                smp_store_release(&(v)->counter, i);
@@ -4657,4 +4649,4 @@ raw_atomic64_dec_if_positive(atomic64_t *v)
 }
 
 #endif /* _LINUX_ATOMIC_FALLBACK_H */
-// 202b45c7db600ce36198eb1f1fc2c2d5268ace2d
+// 2fdd6702823fa842f9cea57a002e6e4476ae780c
index a3462a9b8e18547d521d9dc318074f6a69afe5ed..a9cb10b0e2e9bf45c33f4ad39e7a95d8d9b6b1b5 100644 (file)
@@ -49,7 +49,7 @@ word                                                  \
        ____BTF_ID(symbol, word)
 
 #define __ID(prefix) \
-       __PASTE(prefix, __COUNTER__)
+       __PASTE(__PASTE(prefix, __COUNTER__), __LINE__)
 
 /*
  * The BTF_ID defines unique symbol for each ID pointing
index 4ede47649a811801f07a8aba4a392a35e1593c8e..44e9de51eedfb634aa2a44420a0fc32ee61ff924 100644 (file)
@@ -171,7 +171,10 @@ static __always_inline int buffer_uptodate(const struct buffer_head *bh)
        return test_bit_acquire(BH_Uptodate, &bh->b_state);
 }
 
-#define bh_offset(bh)          ((unsigned long)(bh)->b_data & ~PAGE_MASK)
+static inline unsigned long bh_offset(const struct buffer_head *bh)
+{
+       return (unsigned long)(bh)->b_data & (page_size(bh->b_page) - 1);
+}
 
 /* If we *know* page->private refers to buffer_heads */
 #define page_buffers(page)                                     \
index 06dda85f042445bb0d4b017b7e2aecd5b0587651..068f7738be22ab17b9958d01d46f92bec0d903f7 100644 (file)
@@ -90,7 +90,6 @@ enum cpuhp_state {
        CPUHP_FS_BUFF_DEAD,
        CPUHP_PRINTK_DEAD,
        CPUHP_MM_MEMCQ_DEAD,
-       CPUHP_XFS_DEAD,
        CPUHP_PERCPU_CNT_DEAD,
        CPUHP_RADIX_DEAD,
        CPUHP_PAGE_ALLOC,
index 1c849db953a51a71809c9b428f5b092507473149..45fca09b231943ea38f56f5079ba7e431074f8a9 100644 (file)
@@ -52,6 +52,8 @@
 
 #ifdef CONFIG_IA64
 #define KSYM_FUNC(name)                @fptr(name)
+#elif defined(CONFIG_PARISC) && defined(CONFIG_64BIT)
+#define KSYM_FUNC(name)                P%name
 #else
 #define KSYM_FUNC(name)                name
 #endif
index 4aeb3fa1192771cdd8e1e1ebdf18f9b08c983166..b528f063e8ffaa32a45e1b14398f448445771aa6 100644 (file)
@@ -1508,47 +1508,18 @@ static inline bool fsuidgid_has_mapping(struct super_block *sb,
               kgid_has_mapping(fs_userns, kgid);
 }
 
-struct timespec64 current_mgtime(struct inode *inode);
 struct timespec64 current_time(struct inode *inode);
 struct timespec64 inode_set_ctime_current(struct inode *inode);
 
-/*
- * Multigrain timestamps
- *
- * Conditionally use fine-grained ctime and mtime timestamps when there
- * are users actively observing them via getattr. The primary use-case
- * for this is NFS clients that use the ctime to distinguish between
- * different states of the file, and that are often fooled by multiple
- * operations that occur in the same coarse-grained timer tick.
- *
- * The kernel always keeps normalized struct timespec64 values in the ctime,
- * which means that only the first 30 bits of the value are used. Use the
- * 31st bit of the ctime's tv_nsec field as a flag to indicate that the value
- * has been queried since it was last updated.
- */
-#define I_CTIME_QUERIED                (1L<<30)
-
 /**
  * inode_get_ctime - fetch the current ctime from the inode
  * @inode: inode from which to fetch ctime
  *
- * Grab the current ctime tv_nsec field from the inode, mask off the
- * I_CTIME_QUERIED flag and return it. This is mostly intended for use by
- * internal consumers of the ctime that aren't concerned with ensuring a
- * fine-grained update on the next change (e.g. when preparing to store
- * the value in the backing store for later retrieval).
- *
- * This is safe to call regardless of whether the underlying filesystem
- * is using multigrain timestamps.
+ * Grab the current ctime from the inode and return it.
  */
 static inline struct timespec64 inode_get_ctime(const struct inode *inode)
 {
-       struct timespec64 ctime;
-
-       ctime.tv_sec = inode->__i_ctime.tv_sec;
-       ctime.tv_nsec = inode->__i_ctime.tv_nsec & ~I_CTIME_QUERIED;
-
-       return ctime;
+       return inode->__i_ctime;
 }
 
 /**
@@ -2334,7 +2305,6 @@ struct file_system_type {
 #define FS_USERNS_MOUNT                8       /* Can be mounted by userns root */
 #define FS_DISALLOW_NOTIFY_PERM        16      /* Disable fanotify permission events */
 #define FS_ALLOW_IDMAP         32      /* FS has been updated to handle vfs idmappings. */
-#define FS_MGTIME              64      /* FS uses multigrain timestamps */
 #define FS_RENAME_DOES_D_MOVE  32768   /* FS will handle d_move() during rename() internally. */
        int (*init_fs_context)(struct fs_context *);
        const struct fs_parameter_spec *parameters;
@@ -2358,17 +2328,6 @@ struct file_system_type {
 
 #define MODULE_ALIAS_FS(NAME) MODULE_ALIAS("fs-" NAME)
 
-/**
- * is_mgtime: is this inode using multigrain timestamps
- * @inode: inode to test for multigrain timestamps
- *
- * Return true if the inode uses multigrain timestamps, false otherwise.
- */
-static inline bool is_mgtime(const struct inode *inode)
-{
-       return inode->i_sb->s_type->fs_flags & FS_MGTIME;
-}
-
 extern struct dentry *mount_bdev(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data,
        int (*fill_super)(struct super_block *, void *, int));
@@ -3054,7 +3013,6 @@ extern void page_put_link(void *);
 extern int page_symlink(struct inode *inode, const char *symname, int len);
 extern const struct inode_operations page_symlink_inode_operations;
 extern void kfree_link(void *);
-void fill_mg_cmtime(struct kstat *stat, u32 request_mask, struct inode *inode);
 void generic_fillattr(struct mnt_idmap *, u32, struct inode *, struct kstat *);
 void generic_fill_statx_attr(struct inode *inode, struct kstat *stat);
 extern int vfs_getattr_nosec(const struct path *, struct kstat *, u32, unsigned int);
index 3430cc2b05a696eb0444c8e88db0740ebb5ee34e..0dae9db275380b16bada4327f8f02e53ff8db30f 100644 (file)
@@ -237,7 +237,6 @@ enum i2c_driver_flags {
  * struct i2c_driver - represent an I2C device driver
  * @class: What kind of i2c device we instantiate (for detect)
  * @probe: Callback for device binding
- * @probe_new: Transitional callback for device binding - do not use
  * @remove: Callback for device unbinding
  * @shutdown: Callback for device shutdown
  * @alert: Alert callback, for example for the SMBus alert protocol
@@ -272,16 +271,8 @@ enum i2c_driver_flags {
 struct i2c_driver {
        unsigned int class;
 
-       union {
        /* Standard driver model interfaces */
-               int (*probe)(struct i2c_client *client);
-               /*
-                * Legacy callback that was part of a conversion of .probe().
-                * Today it has the same semantic as .probe(). Don't use for new
-                * code.
-                */
-               int (*probe_new)(struct i2c_client *client);
-       };
+       int (*probe)(struct i2c_client *client);
        void (*remove)(struct i2c_client *client);
 
 
index 1b9b15a492fae417f87b946fe343f7ee29ec890b..cdc684e04a2fb6fcabda07a3427270af79b7eca8 100644 (file)
@@ -189,6 +189,8 @@ struct team {
        struct net_device *dev; /* associated netdevice */
        struct team_pcpu_stats __percpu *pcpu_stats;
 
+       const struct header_ops *header_ops_cache;
+
        struct mutex lock; /* used for overall locking, e.g. port lists write */
 
        /*
index cda1f706eaeb1186972eab1ca88e5d8584fcd9e1..aa0b3ffea93536c7b423742f09efbaee50c7f56e 100644 (file)
@@ -2,7 +2,12 @@
 #ifndef _LINUX_INSTRUCTION_POINTER_H
 #define _LINUX_INSTRUCTION_POINTER_H
 
+#include <asm/linkage.h>
+
 #define _RET_IP_               (unsigned long)__builtin_return_address(0)
+
+#ifndef _THIS_IP_
 #define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })
+#endif
 
 #endif /* _LINUX_INSTRUCTION_POINTER_H */
index 3df5499f79369df25448c3069f00888d0cbb31f2..842623d708c2e0625e23d7439071eae31c2c6cc0 100644 (file)
@@ -54,7 +54,7 @@ extern p4d_t kasan_early_shadow_p4d[MAX_PTRS_PER_P4D];
 int kasan_populate_early_shadow(const void *shadow_start,
                                const void *shadow_end);
 
-#ifndef __HAVE_ARCH_SHADOW_MAP
+#ifndef kasan_mem_to_shadow
 static inline void *kasan_mem_to_shadow(const void *addr)
 {
        return (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT)
index 52d58b13e5eee7e5b004fb84dd0fba853f2ea0dc..bf4913f4d7ac1710c258b61e0e2f9ef201a24c04 100644 (file)
@@ -222,6 +222,10 @@ enum {
        ATA_HOST_PARALLEL_SCAN  = (1 << 2),     /* Ports on this host can be scanned in parallel */
        ATA_HOST_IGNORE_ATA     = (1 << 3),     /* Ignore ATA devices on this host. */
 
+       ATA_HOST_NO_PART        = (1 << 4), /* Host does not support partial */
+       ATA_HOST_NO_SSC         = (1 << 5), /* Host does not support slumber */
+       ATA_HOST_NO_DEVSLP      = (1 << 6), /* Host does not support devslp */
+
        /* bits 24:31 of host->flags are reserved for LLD specific flags */
 
        /* various lengths of time */
index ab94ad4597d07373b813f110092ebaa3cf5527c5..e4e24da16d2c398493e197cfb97f25be9940e3d0 100644 (file)
@@ -920,7 +920,7 @@ unsigned long mem_cgroup_get_zone_lru_size(struct lruvec *lruvec,
        return READ_ONCE(mz->lru_zone_size[zone_idx][lru]);
 }
 
-void mem_cgroup_handle_over_high(void);
+void mem_cgroup_handle_over_high(gfp_t gfp_mask);
 
 unsigned long mem_cgroup_get_max(struct mem_cgroup *memcg);
 
@@ -1458,7 +1458,7 @@ static inline void mem_cgroup_unlock_pages(void)
        rcu_read_unlock();
 }
 
-static inline void mem_cgroup_handle_over_high(void)
+static inline void mem_cgroup_handle_over_high(gfp_t gfp_mask)
 {
 }
 
index 20eeba8b009df1100a3c6080f84c93277aaba4dc..cd628c4b011e54fa807674daa8a3361c97c20a5f 100644 (file)
@@ -48,6 +48,7 @@ struct nfs_client {
 #define NFS_CS_NOPING          6               /* - don't ping on connect */
 #define NFS_CS_DS              7               /* - Server is a DS */
 #define NFS_CS_REUSEPORT       8               /* - reuse src port on reconnect */
+#define NFS_CS_PNFS            9               /* - Server used for pnfs */
        struct sockaddr_storage cl_addr;        /* server identifier */
        size_t                  cl_addrlen;
        char *                  cl_hostname;    /* hostname of server */
index aa9f4c6ebe261d40fc3dc21389a97458e1722178..1c315f854ea8013bef87fb820dd0186aefb4a3cf 100644 (file)
@@ -157,7 +157,9 @@ extern      void nfs_unlock_request(struct nfs_page *req);
 extern void nfs_unlock_and_release_request(struct nfs_page *);
 extern struct nfs_page *nfs_page_group_lock_head(struct nfs_page *req);
 extern int nfs_page_group_lock_subrequests(struct nfs_page *head);
-extern void nfs_join_page_group(struct nfs_page *head, struct inode *inode);
+extern void nfs_join_page_group(struct nfs_page *head,
+                               struct nfs_commit_info *cinfo,
+                               struct inode *inode);
 extern int nfs_page_group_lock(struct nfs_page *);
 extern void nfs_page_group_unlock(struct nfs_page *);
 extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int);
index f6ef8cf5d7741f924f92600ad7dbb9bcf5fb7227..4109f1bd61285b3ada18af6ec26f34380162cff4 100644 (file)
 struct nvmefc_ls_req {
        void                    *rqstaddr;
        dma_addr_t              rqstdma;
-       __le32                  rqstlen;
+       u32                     rqstlen;
        void                    *rspaddr;
        dma_addr_t              rspdma;
-       __le32                  rsplen;
+       u32                     rsplen;
        u32                     timeout;
 
        void                    *private;
@@ -120,7 +120,7 @@ struct nvmefc_ls_req {
 struct nvmefc_ls_rsp {
        void            *rspbuf;
        dma_addr_t      rspdma;
-       __le32          rsplen;
+       u16             rsplen;
 
        void (*done)(struct nvmefc_ls_rsp *rsp);
        void            *nvme_fc_private;       /* LLDD is not to access !! */
index 28518945444968fed623838f4028dca96736a9f7..f8f3e958e9cf2fbf0777fdbf5e3fd993c889cee3 100644 (file)
@@ -55,7 +55,7 @@ static inline void resume_user_mode_work(struct pt_regs *regs)
        }
 #endif
 
-       mem_cgroup_handle_over_high();
+       mem_cgroup_handle_over_high(GFP_KERNEL);
        blkcg_maybe_throttle_current();
 
        rseq_handle_notify_resume(NULL, regs);
index 987a59d977c566ae5eb0f306e4ed79f4e5428204..e9bd2f65d7f4e40d10cfe11b4fe5d433be4273db 100644 (file)
@@ -512,8 +512,8 @@ do {                                                                        \
 
 static inline void do_write_seqcount_begin_nested(seqcount_t *s, int subclass)
 {
-       do_raw_write_seqcount_begin(s);
        seqcount_acquire(&s->dep_map, subclass, 0, _RET_IP_);
+       do_raw_write_seqcount_begin(s);
 }
 
 /**
index 5b4fb3c791bc267042a9af1b7384e606ae0b043f..2f8dc47f1eb07504903318682a58ec8735ac4c5d 100644 (file)
@@ -779,7 +779,9 @@ xdr_stream_decode_uint32_array(struct xdr_stream *xdr,
 
        if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0))
                return -EBADMSG;
-       p = xdr_inline_decode(xdr, size_mul(len, sizeof(*p)));
+       if (U32_MAX >= SIZE_MAX / sizeof(*p) && len > SIZE_MAX / sizeof(*p))
+               return -EBADMSG;
+       p = xdr_inline_decode(xdr, len * sizeof(*p));
        if (unlikely(!p))
                return -EBADMSG;
        if (array == NULL)
index c99440aac1a11dfd59497fa4d1cce94c1668afcf..a5ae4af955ff926f9b9d49c30cab61a4f0f9f45e 100644 (file)
@@ -80,8 +80,8 @@ struct thermal_zone_device_ops {
        int (*set_trip_hyst) (struct thermal_zone_device *, int, int);
        int (*get_crit_temp) (struct thermal_zone_device *, int *);
        int (*set_emul_temp) (struct thermal_zone_device *, int);
-       int (*get_trend) (struct thermal_zone_device *, struct thermal_trip *,
-                         enum thermal_trend *);
+       int (*get_trend) (struct thermal_zone_device *,
+                         const struct thermal_trip *, enum thermal_trend *);
        void (*hot)(struct thermal_zone_device *);
        void (*critical)(struct thermal_zone_device *);
 };
index eb5c3add939b78f69a4f5b25449283c50d861579..21ae37e49319a13287ef895c51e1362ed20aeca7 100644 (file)
@@ -62,13 +62,13 @@ void trace_event_printf(struct trace_iterator *iter, const char *fmt, ...);
 /* Used to find the offset and length of dynamic fields in trace events */
 struct trace_dynamic_info {
 #ifdef CONFIG_CPU_BIG_ENDIAN
-       u16     offset;
        u16     len;
+       u16     offset;
 #else
-       u16     len;
        u16     offset;
+       u16     len;
 #endif
-};
+} __packed;
 
 /*
  * The trace entry - the most basic unit of tracing. This is what
@@ -650,7 +650,6 @@ struct trace_event_file {
        struct trace_event_call         *event_call;
        struct event_filter __rcu       *filter;
        struct eventfs_file             *ef;
-       struct dentry                   *dir;
        struct trace_array              *tr;
        struct trace_subsystem_dir      *system;
        struct list_head                triggers;
index 0675be0f3fa0efc55575bb5b2569dc8a1dbb9f24..c6932d1a3fa806ab9d72948994dbf3b7ac742b1c 100644 (file)
@@ -784,6 +784,11 @@ static inline bool ipv6_addr_v4mapped(const struct in6_addr *a)
                                        cpu_to_be32(0x0000ffff))) == 0UL;
 }
 
+static inline bool ipv6_addr_v4mapped_any(const struct in6_addr *a)
+{
+       return ipv6_addr_v4mapped(a) && ipv4_is_zeronet(a->s6_addr32[3]);
+}
+
 static inline bool ipv6_addr_v4mapped_loopback(const struct in6_addr *a)
 {
        return ipv6_addr_v4mapped(a) && ipv4_is_loopback(a->s6_addr32[3]);
@@ -1360,7 +1365,7 @@ static inline int __ip6_sock_set_addr_preferences(struct sock *sk, int val)
        return 0;
 }
 
-static inline int ip6_sock_set_addr_preferences(struct sock *sk, bool val)
+static inline int ip6_sock_set_addr_preferences(struct sock *sk, int val)
 {
        int ret;
 
index dd40c75011d25fdf8ce2360c9b291ebc4ee6104b..7c816359d5a98884cf303b87af1bb2adbb1b48e2 100644 (file)
@@ -1682,7 +1682,7 @@ struct nft_trans_gc {
        struct net              *net;
        struct nft_set          *set;
        u32                     seq;
-       u                     count;
+       u16                     count;
        void                    *priv[NFT_TRANS_GC_BATCHCOUNT];
        struct rcu_head         rcu;
 };
@@ -1700,8 +1700,9 @@ void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans);
 
 void nft_trans_gc_elem_add(struct nft_trans_gc *gc, void *priv);
 
-struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
-                                          unsigned int gc_seq);
+struct nft_trans_gc *nft_trans_gc_catchall_async(struct nft_trans_gc *gc,
+                                                unsigned int gc_seq);
+struct nft_trans_gc *nft_trans_gc_catchall_sync(struct nft_trans_gc *gc);
 
 void nft_setelem_data_deactivate(const struct net *net,
                                 const struct nft_set *set,
index 44a3f565264d931b1b9257ad4090e5182f322bb6..0577f0cdd23162d6abd7a88b005d9479a7c0f5b0 100644 (file)
@@ -6,26 +6,26 @@
 #define _TRACE_XEN_H
 
 #include <linux/tracepoint.h>
-#include <asm/paravirt_types.h>
+#include <asm/xen/hypervisor.h>
 #include <asm/xen/trace_types.h>
 
 struct multicall_entry;
 
 /* Multicalls */
 DECLARE_EVENT_CLASS(xen_mc__batch,
-           TP_PROTO(enum paravirt_lazy_mode mode),
+           TP_PROTO(enum xen_lazy_mode mode),
            TP_ARGS(mode),
            TP_STRUCT__entry(
-                   __field(enum paravirt_lazy_mode, mode)
+                   __field(enum xen_lazy_mode, mode)
                    ),
            TP_fast_assign(__entry->mode = mode),
            TP_printk("start batch LAZY_%s",
-                     (__entry->mode == PARAVIRT_LAZY_MMU) ? "MMU" :
-                     (__entry->mode == PARAVIRT_LAZY_CPU) ? "CPU" : "NONE")
+                     (__entry->mode == XEN_LAZY_MMU) ? "MMU" :
+                     (__entry->mode == XEN_LAZY_CPU) ? "CPU" : "NONE")
        );
 #define DEFINE_XEN_MC_BATCH(name)                      \
        DEFINE_EVENT(xen_mc__batch, name,               \
-               TP_PROTO(enum paravirt_lazy_mode mode), \
+               TP_PROTO(enum xen_lazy_mode mode),      \
                     TP_ARGS(mode))
 
 DEFINE_XEN_MC_BATCH(xen_mc_batch);
index 8790b3962e4b85f22593f8f9c9f8d94eaf6981f3..0448700890f77d9a4fffa6fed5c17aa02b9f718b 100644 (file)
@@ -1962,7 +1962,9 @@ union bpf_attr {
  *             performed again, if the helper is used in combination with
  *             direct packet access.
  *     Return
- *             0 on success, or a negative error in case of failure.
+ *             0 on success, or a negative error in case of failure. Positive
+ *             error indicates a potential drop or congestion in the target
+ *             device. The particular positive error codes are not defined.
  *
  * u64 bpf_get_current_pid_tgid(void)
  *     Description
index 7c3fc39808811022b849d9f715b7b6c62a10ef18..5c6c4269f7efe4d649366907191adfbcffef41e4 100644 (file)
                struct TAG { MEMBERS } ATTRS NAME; \
        }
 
+#ifdef __cplusplus
+/* sizeof(struct{}) is 1 in C++, not 0, can't use C version of the macro. */
+#define __DECLARE_FLEX_ARRAY(T, member)        \
+       T member[0]
+#else
 /**
  * __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union
  *
@@ -49,3 +54,5 @@
 #ifndef __counted_by
 #define __counted_by(m)
 #endif
+
+#endif /* _UAPI_LINUX_STDDEF_H */
index 43ef24dd030e10237a97373e635632ae5a8e4a9c..9995695204f5d25730ddbc6c9663117eac557072 100644 (file)
@@ -7,18 +7,6 @@
 extern struct shared_info *HYPERVISOR_shared_info;
 extern struct start_info *xen_start_info;
 
-/* Lazy mode for batching updates / context switch */
-enum paravirt_lazy_mode {
-       PARAVIRT_LAZY_NONE,
-       PARAVIRT_LAZY_MMU,
-       PARAVIRT_LAZY_CPU,
-};
-
-static inline enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
-{
-       return PARAVIRT_LAZY_NONE;
-}
-
 #ifdef CONFIG_XEN
 void __init xen_early_init(void);
 #else
index 95d5e28de324af3c46f1fd876e7e3e26c8120c70..23932b0673dc7459037c16e97642598a16f08877 100644 (file)
@@ -105,8 +105,7 @@ int irq_from_virq(unsigned int cpu, unsigned int virq);
 evtchn_port_t evtchn_from_irq(unsigned irq);
 
 int xen_set_callback_via(uint64_t via);
-void xen_evtchn_do_upcall(struct pt_regs *regs);
-int xen_hvm_evtchn_do_upcall(void);
+int xen_evtchn_do_upcall(void);
 
 /* Bind a pirq for a physical interrupt to an irq. */
 int xen_bind_pirq_gsi_to_irq(unsigned gsi,
index 3d07bf79c1e025eb900eace985d14804ed392b2c..7a8e298af81b3b1db393efc547d04a8f2938f091 100644 (file)
@@ -183,6 +183,10 @@ static int io_setup_async_msg(struct io_kiocb *req,
        memcpy(async_msg, kmsg, sizeof(*kmsg));
        if (async_msg->msg.msg_name)
                async_msg->msg.msg_name = &async_msg->addr;
+
+       if ((req->flags & REQ_F_BUFFER_SELECT) && !async_msg->msg.msg_iter.nr_segs)
+               return -EAGAIN;
+
        /* if were using fast_iov, set it to the new one */
        if (iter_is_iovec(&kmsg->msg.msg_iter) && !kmsg->free_iov) {
                size_t fast_idx = iter_iov(&kmsg->msg.msg_iter) - kmsg->fast_iov;
@@ -542,6 +546,7 @@ static int io_recvmsg_copy_hdr(struct io_kiocb *req,
                               struct io_async_msghdr *iomsg)
 {
        iomsg->msg.msg_name = &iomsg->addr;
+       iomsg->msg.msg_iter.nr_segs = 0;
 
 #ifdef CONFIG_COMPAT
        if (req->ctx->compat)
index 1095bbe2985930f486010f955d96ee7b57d0a8a1..8090d7fb11ef686019b4734bbc7151057ee78efa 100644 (file)
@@ -8501,7 +8501,7 @@ bool btf_nested_type_is_trusted(struct bpf_verifier_log *log,
        tname = btf_name_by_offset(btf, walk_type->name_off);
 
        ret = snprintf(safe_tname, sizeof(safe_tname), "%s%s", tname, suffix);
-       if (ret < 0)
+       if (ret >= sizeof(safe_tname))
                return false;
 
        safe_id = btf_find_by_name_kind(btf, safe_tname, BTF_INFO_KIND(walk_type->info));
index 5b2741aa0d9bb8e01d630ca548eb39ce10553e6a..03b3d4492980d04f33f63235c6fef18ee2667702 100644 (file)
@@ -785,7 +785,8 @@ found:
  *                          to descendants
  * @cgrp: The cgroup which descendants to traverse
  * @link: A link for which to replace BPF program
- * @type: Type of attach operation
+ * @new_prog: &struct bpf_prog for the target BPF program with its refcnt
+ *            incremented
  *
  * Must be called with cgroup_mutex held.
  */
@@ -1334,7 +1335,7 @@ int cgroup_bpf_prog_query(const union bpf_attr *attr,
  * __cgroup_bpf_run_filter_skb() - Run a program for packet filtering
  * @sk: The socket sending or receiving traffic
  * @skb: The skb that is being sent or received
- * @type: The type of program to be executed
+ * @atype: The type of program to be executed
  *
  * If no socket is passed, or the socket is not of type INET or INET6,
  * this function does nothing and returns 0.
@@ -1424,7 +1425,7 @@ EXPORT_SYMBOL(__cgroup_bpf_run_filter_skb);
 /**
  * __cgroup_bpf_run_filter_sk() - Run a program on a sock
  * @sk: sock structure to manipulate
- * @type: The type of program to be executed
+ * @atype: The type of program to be executed
  *
  * socket is passed is expected to be of type INET or INET6.
  *
@@ -1449,7 +1450,7 @@ EXPORT_SYMBOL(__cgroup_bpf_run_filter_sk);
  *                                       provided by user sockaddr
  * @sk: sock struct that will use sockaddr
  * @uaddr: sockaddr struct provided by user
- * @type: The type of program to be executed
+ * @atype: The type of program to be executed
  * @t_ctx: Pointer to attach type specific context
  * @flags: Pointer to u32 which contains higher bits of BPF program
  *         return value (OR'ed together).
@@ -1496,7 +1497,7 @@ EXPORT_SYMBOL(__cgroup_bpf_run_filter_sock_addr);
  * @sock_ops: bpf_sock_ops_kern struct to pass to program. Contains
  * sk with connection information (IP addresses, etc.) May not contain
  * cgroup info if it is a req sock.
- * @type: The type of program to be executed
+ * @atype: The type of program to be executed
  *
  * socket passed is expected to be of type INET or INET6.
  *
@@ -1670,7 +1671,7 @@ const struct bpf_verifier_ops cg_dev_verifier_ops = {
  * @ppos: value-result argument: value is position at which read from or write
  *     to sysctl is happening, result is new position if program overrode it,
  *     initial value otherwise
- * @type: type of program to be executed
+ * @atype: type of program to be executed
  *
  * Program is run when sysctl is being accessed, either read or written, and
  * can allow or deny such access.
index 9c49ae53deaf81f9e22fefc376657492abd2ebb9..cf19415166437c87fe04b9f948cb75033a701033 100644 (file)
@@ -459,8 +459,7 @@ static void notrace irq_work_raise(struct bpf_mem_cache *c)
  * Typical case will be between 11K and 116K closer to 11K.
  * bpf progs can and should share bpf_mem_cache when possible.
  */
-
-static void prefill_mem_cache(struct bpf_mem_cache *c, int cpu)
+static void init_refill_work(struct bpf_mem_cache *c)
 {
        init_irq_work(&c->refill_work, bpf_mem_refill);
        if (c->unit_size <= 256) {
@@ -476,7 +475,10 @@ static void prefill_mem_cache(struct bpf_mem_cache *c, int cpu)
                c->high_watermark = max(96 * 256 / c->unit_size, 3);
        }
        c->batch = max((c->high_watermark - c->low_watermark) / 4 * 3, 1);
+}
 
+static void prefill_mem_cache(struct bpf_mem_cache *c, int cpu)
+{
        /* To avoid consuming memory assume that 1st run of bpf
         * prog won't be doing more than 4 map_update_elem from
         * irq disabled region
@@ -484,6 +486,31 @@ static void prefill_mem_cache(struct bpf_mem_cache *c, int cpu)
        alloc_bulk(c, c->unit_size <= 256 ? 4 : 1, cpu_to_node(cpu), false);
 }
 
+static int check_obj_size(struct bpf_mem_cache *c, unsigned int idx)
+{
+       struct llist_node *first;
+       unsigned int obj_size;
+
+       /* For per-cpu allocator, the size of free objects in free list doesn't
+        * match with unit_size and now there is no way to get the size of
+        * per-cpu pointer saved in free object, so just skip the checking.
+        */
+       if (c->percpu_size)
+               return 0;
+
+       first = c->free_llist.first;
+       if (!first)
+               return 0;
+
+       obj_size = ksize(first);
+       if (obj_size != c->unit_size) {
+               WARN_ONCE(1, "bpf_mem_cache[%u]: unexpected object size %u, expect %u\n",
+                         idx, obj_size, c->unit_size);
+               return -EINVAL;
+       }
+       return 0;
+}
+
 /* When size != 0 bpf_mem_cache for each cpu.
  * This is typical bpf hash map use case when all elements have equal size.
  *
@@ -494,10 +521,10 @@ static void prefill_mem_cache(struct bpf_mem_cache *c, int cpu)
 int bpf_mem_alloc_init(struct bpf_mem_alloc *ma, int size, bool percpu)
 {
        static u16 sizes[NUM_CACHES] = {96, 192, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096};
+       int cpu, i, err, unit_size, percpu_size = 0;
        struct bpf_mem_caches *cc, __percpu *pcc;
        struct bpf_mem_cache *c, __percpu *pc;
        struct obj_cgroup *objcg = NULL;
-       int cpu, i, unit_size, percpu_size = 0;
 
        if (size) {
                pc = __alloc_percpu_gfp(sizeof(*pc), 8, GFP_KERNEL);
@@ -521,6 +548,7 @@ int bpf_mem_alloc_init(struct bpf_mem_alloc *ma, int size, bool percpu)
                        c->objcg = objcg;
                        c->percpu_size = percpu_size;
                        c->tgt = c;
+                       init_refill_work(c);
                        prefill_mem_cache(c, cpu);
                }
                ma->cache = pc;
@@ -534,6 +562,7 @@ int bpf_mem_alloc_init(struct bpf_mem_alloc *ma, int size, bool percpu)
        pcc = __alloc_percpu_gfp(sizeof(*cc), 8, GFP_KERNEL);
        if (!pcc)
                return -ENOMEM;
+       err = 0;
 #ifdef CONFIG_MEMCG_KMEM
        objcg = get_obj_cgroup_from_current();
 #endif
@@ -544,11 +573,30 @@ int bpf_mem_alloc_init(struct bpf_mem_alloc *ma, int size, bool percpu)
                        c->unit_size = sizes[i];
                        c->objcg = objcg;
                        c->tgt = c;
+
+                       init_refill_work(c);
+                       /* Another bpf_mem_cache will be used when allocating
+                        * c->unit_size in bpf_mem_alloc(), so doesn't prefill
+                        * for the bpf_mem_cache because these free objects will
+                        * never be used.
+                        */
+                       if (i != bpf_mem_cache_idx(c->unit_size))
+                               continue;
                        prefill_mem_cache(c, cpu);
+                       err = check_obj_size(c, i);
+                       if (err)
+                               goto out;
                }
        }
+
+out:
        ma->caches = pcc;
-       return 0;
+       /* refill_work is either zeroed or initialized, so it is safe to
+        * call irq_work_sync().
+        */
+       if (err)
+               bpf_mem_alloc_destroy(ma);
+       return err;
 }
 
 static void drain_mem_cache(struct bpf_mem_cache *c)
@@ -916,3 +964,41 @@ void notrace *bpf_mem_cache_alloc_flags(struct bpf_mem_alloc *ma, gfp_t flags)
 
        return !ret ? NULL : ret + LLIST_NODE_SZ;
 }
+
+/* Most of the logic is taken from setup_kmalloc_cache_index_table() */
+static __init int bpf_mem_cache_adjust_size(void)
+{
+       unsigned int size, index;
+
+       /* Normally KMALLOC_MIN_SIZE is 8-bytes, but it can be
+        * up-to 256-bytes.
+        */
+       size = KMALLOC_MIN_SIZE;
+       if (size <= 192)
+               index = size_index[(size - 1) / 8];
+       else
+               index = fls(size - 1) - 1;
+       for (size = 8; size < KMALLOC_MIN_SIZE && size <= 192; size += 8)
+               size_index[(size - 1) / 8] = index;
+
+       /* The minimal alignment is 64-bytes, so disable 96-bytes cache and
+        * use 128-bytes cache instead.
+        */
+       if (KMALLOC_MIN_SIZE >= 64) {
+               index = size_index[(128 - 1) / 8];
+               for (size = 64 + 8; size <= 96; size += 8)
+                       size_index[(size - 1) / 8] = index;
+       }
+
+       /* The minimal alignment is 128-bytes, so disable 192-bytes cache and
+        * use 256-bytes cache instead.
+        */
+       if (KMALLOC_MIN_SIZE >= 128) {
+               index = fls(256 - 1) - 1;
+               for (size = 128 + 8; size <= 192; size += 8)
+                       size_index[(size - 1) / 8] = index;
+       }
+
+       return 0;
+}
+subsys_initcall(bpf_mem_cache_adjust_size);
index 3e4f2ec1af0687dc92d74a376072ab3a77d7b5e3..87d6693d8233f1aa3a1283e73600c9cd6fdf3cdf 100644 (file)
@@ -199,12 +199,14 @@ static int __bpf_prog_dev_bound_init(struct bpf_prog *prog, struct net_device *n
        offload->netdev = netdev;
 
        ondev = bpf_offload_find_netdev(offload->netdev);
+       /* When program is offloaded require presence of "true"
+        * bpf_offload_netdev, avoid the one created for !ondev case below.
+        */
+       if (bpf_prog_is_offloaded(prog->aux) && (!ondev || !ondev->offdev)) {
+               err = -EINVAL;
+               goto err_free;
+       }
        if (!ondev) {
-               if (bpf_prog_is_offloaded(prog->aux)) {
-                       err = -EINVAL;
-                       goto err_free;
-               }
-
                /* When only binding to the device, explicitly
                 * create an entry in the hashtable.
                 */
index 8d2ddcb7566b7fe262e7571700f1b1ac48dcc782..d869f51ea93a0e918d365729ee5bcd8687a5ce4f 100644 (file)
@@ -98,7 +98,12 @@ static long __queue_map_get(struct bpf_map *map, void *value, bool delete)
        int err = 0;
        void *ptr;
 
-       raw_spin_lock_irqsave(&qs->lock, flags);
+       if (in_nmi()) {
+               if (!raw_spin_trylock_irqsave(&qs->lock, flags))
+                       return -EBUSY;
+       } else {
+               raw_spin_lock_irqsave(&qs->lock, flags);
+       }
 
        if (queue_stack_map_is_empty(qs)) {
                memset(value, 0, qs->map.value_size);
@@ -128,7 +133,12 @@ static long __stack_map_get(struct bpf_map *map, void *value, bool delete)
        void *ptr;
        u32 index;
 
-       raw_spin_lock_irqsave(&qs->lock, flags);
+       if (in_nmi()) {
+               if (!raw_spin_trylock_irqsave(&qs->lock, flags))
+                       return -EBUSY;
+       } else {
+               raw_spin_lock_irqsave(&qs->lock, flags);
+       }
 
        if (queue_stack_map_is_empty(qs)) {
                memset(value, 0, qs->map.value_size);
@@ -193,7 +203,12 @@ static long queue_stack_map_push_elem(struct bpf_map *map, void *value,
        if (flags & BPF_NOEXIST || flags > BPF_EXIST)
                return -EINVAL;
 
-       raw_spin_lock_irqsave(&qs->lock, irq_flags);
+       if (in_nmi()) {
+               if (!raw_spin_trylock_irqsave(&qs->lock, irq_flags))
+                       return -EBUSY;
+       } else {
+               raw_spin_lock_irqsave(&qs->lock, irq_flags);
+       }
 
        if (queue_stack_map_is_full(qs)) {
                if (!replace) {
index 07239d4ad81e87e1de4477f8196e8ffcd105161b..ffa037fa777d5f7f1cb8596893fe90c3fb0a2f46 100644 (file)
@@ -697,6 +697,7 @@ void warn_slowpath_fmt(const char *file, int line, unsigned taint,
        if (!fmt) {
                __warn(file, line, __builtin_return_address(0), taint,
                       NULL, NULL);
+               warn_rcu_exit(rcu);
                return;
        }
 
index fee14a4486a310ee650e1249b3a85d0719f9a7a7..6500ef956f2f885793833e160891b4f441acd104 100644 (file)
@@ -609,7 +609,7 @@ int pidfd_create(struct pid *pid, unsigned int flags)
 }
 
 /**
- * pidfd_open() - Open new pid file descriptor.
+ * sys_pidfd_open() - Open new pid file descriptor.
  *
  * @pid:   pid for which to retrieve a pidfd
  * @flags: flags to pass
index 2b4a946a6ff5cfcae69fd9e03ee1d5cc0728736e..8d35b9f9aaa3f203e3f2bb103c2cce72fbc44157 100644 (file)
@@ -786,9 +786,9 @@ int hibernate(void)
        unlock_device_hotplug();
        if (snapshot_test) {
                pm_pr_dbg("Checking hibernation image\n");
-               error = swsusp_check(snapshot_test);
+               error = swsusp_check(false);
                if (!error)
-                       error = load_image_and_restore(snapshot_test);
+                       error = load_image_and_restore(false);
        }
        thaw_processes();
 
@@ -945,14 +945,14 @@ static int software_resume(void)
        pm_pr_dbg("Looking for hibernation image.\n");
 
        mutex_lock(&system_transition_mutex);
-       error = swsusp_check(false);
+       error = swsusp_check(true);
        if (error)
                goto Unlock;
 
        /* The snapshot device should not be opened while we're running */
        if (!hibernate_acquire()) {
                error = -EBUSY;
-               swsusp_close(false);
+               swsusp_close(true);
                goto Unlock;
        }
 
@@ -973,7 +973,7 @@ static int software_resume(void)
                goto Close_Finish;
        }
 
-       error = load_image_and_restore(false);
+       error = load_image_and_restore(true);
        thaw_processes();
  Finish:
        pm_notifier_call_chain(PM_POST_RESTORE);
@@ -987,7 +987,7 @@ static int software_resume(void)
        pm_pr_dbg("Hibernation image not present or could not be loaded.\n");
        return error;
  Close_Finish:
-       swsusp_close(false);
+       swsusp_close(true);
        goto Finish;
 }
 
index 46eb14dc50c31ddef2fb29b4fe9a925002e01c18..a98f95e309a338c5a895ebbdff15f21f2ba730d9 100644 (file)
@@ -168,11 +168,11 @@ extern int swsusp_swap_in_use(void);
 #define SF_HW_SIG              8
 
 /* kernel/power/hibernate.c */
-int swsusp_check(bool snapshot_test);
+int swsusp_check(bool exclusive);
 extern void swsusp_free(void);
 extern int swsusp_read(unsigned int *flags_p);
 extern int swsusp_write(unsigned int flags);
-void swsusp_close(bool snapshot_test);
+void swsusp_close(bool exclusive);
 #ifdef CONFIG_SUSPEND
 extern int swsusp_unmark(void);
 #endif
index f6ebcd00c4100ba1c722501d06092a653e513a8c..74edbce2320bae543c522b97301ec9719725cfa1 100644 (file)
@@ -1513,12 +1513,13 @@ end:
 static void *swsusp_holder;
 
 /**
- *      swsusp_check - Check for swsusp signature in the resume device
+ * swsusp_check - Check for swsusp signature in the resume device
+ * @exclusive: Open the resume device exclusively.
  */
 
-int swsusp_check(bool snapshot_test)
+int swsusp_check(bool exclusive)
 {
-       void *holder = snapshot_test ? &swsusp_holder : NULL;
+       void *holder = exclusive ? &swsusp_holder : NULL;
        int error;
 
        hib_resume_bdev = blkdev_get_by_dev(swsusp_resume_device, BLK_OPEN_READ,
@@ -1563,17 +1564,18 @@ put:
 }
 
 /**
- *     swsusp_close - close swap device.
+ * swsusp_close - close swap device.
+ * @exclusive: Close the resume device which is exclusively opened.
  */
 
-void swsusp_close(bool snapshot_test)
+void swsusp_close(bool exclusive)
 {
        if (IS_ERR(hib_resume_bdev)) {
                pr_debug("Image device not initialised\n");
                return;
        }
 
-       blkdev_put(hib_resume_bdev, snapshot_test ? &swsusp_holder : NULL);
+       blkdev_put(hib_resume_bdev, exclusive ? &swsusp_holder : NULL);
 }
 
 /**
index 2299a5cfbfb9ed250695edb75d977edbe61eaf43..802551e0009bf1ef66191441a802633bb57543bc 100644 (file)
@@ -9269,7 +9269,7 @@ void __init init_idle(struct task_struct *idle, int cpu)
         * PF_KTHREAD should already be set at this point; regardless, make it
         * look like a proper per-CPU kthread.
         */
-       idle->flags |= PF_IDLE | PF_KTHREAD | PF_NO_SETAFFINITY;
+       idle->flags |= PF_KTHREAD | PF_NO_SETAFFINITY;
        kthread_set_per_cpu(idle, cpu);
 
 #ifdef CONFIG_SMP
index 8dbff6e7ad4f53af8965f5ab5ace0c1f2a758c63..cb225921bbca47419eeac08a96c98ac74a57ced2 100644 (file)
@@ -6619,6 +6619,7 @@ dequeue_throttle:
 /* Working cpumask for: load_balance, load_balance_newidle. */
 static DEFINE_PER_CPU(cpumask_var_t, load_balance_mask);
 static DEFINE_PER_CPU(cpumask_var_t, select_rq_mask);
+static DEFINE_PER_CPU(cpumask_var_t, should_we_balance_tmpmask);
 
 #ifdef CONFIG_NO_HZ_COMMON
 
@@ -9579,7 +9580,7 @@ static inline long sibling_imbalance(struct lb_env *env,
        imbalance /= ncores_local + ncores_busiest;
 
        /* Take advantage of resource in an empty sched group */
-       if (imbalance == 0 && local->sum_nr_running == 0 &&
+       if (imbalance <= 1 && local->sum_nr_running == 0 &&
            busiest->sum_nr_running > 1)
                imbalance = 2;
 
@@ -9767,6 +9768,15 @@ static bool update_sd_pick_busiest(struct lb_env *env,
                break;
 
        case group_smt_balance:
+               /*
+                * Check if we have spare CPUs on either SMT group to
+                * choose has spare or fully busy handling.
+                */
+               if (sgs->idle_cpus != 0 || busiest->idle_cpus != 0)
+                       goto has_spare;
+
+               fallthrough;
+
        case group_fully_busy:
                /*
                 * Select the fully busy group with highest avg_load. In
@@ -9806,6 +9816,7 @@ static bool update_sd_pick_busiest(struct lb_env *env,
                        else
                                return true;
                }
+has_spare:
 
                /*
                 * Select not overloaded group with lowest number of idle cpus
@@ -10917,6 +10928,7 @@ static int active_load_balance_cpu_stop(void *data);
 
 static int should_we_balance(struct lb_env *env)
 {
+       struct cpumask *swb_cpus = this_cpu_cpumask_var_ptr(should_we_balance_tmpmask);
        struct sched_group *sg = env->sd->groups;
        int cpu, idle_smt = -1;
 
@@ -10940,8 +10952,9 @@ static int should_we_balance(struct lb_env *env)
                return 1;
        }
 
+       cpumask_copy(swb_cpus, group_balance_mask(sg));
        /* Try to find first idle CPU */
-       for_each_cpu_and(cpu, group_balance_mask(sg), env->cpus) {
+       for_each_cpu_and(cpu, swb_cpus, env->cpus) {
                if (!idle_cpu(cpu))
                        continue;
 
@@ -10953,6 +10966,14 @@ static int should_we_balance(struct lb_env *env)
                if (!(env->sd->flags & SD_SHARE_CPUCAPACITY) && !is_core_idle(cpu)) {
                        if (idle_smt == -1)
                                idle_smt = cpu;
+                       /*
+                        * If the core is not idle, and first SMT sibling which is
+                        * idle has been found, then its not needed to check other
+                        * SMT siblings for idleness:
+                        */
+#ifdef CONFIG_SCHED_SMT
+                       cpumask_andnot(swb_cpus, swb_cpus, cpu_smt_mask(cpu));
+#endif
                        continue;
                }
 
@@ -12918,6 +12939,8 @@ __init void init_sched_fair_class(void)
        for_each_possible_cpu(i) {
                zalloc_cpumask_var_node(&per_cpu(load_balance_mask, i), GFP_KERNEL, cpu_to_node(i));
                zalloc_cpumask_var_node(&per_cpu(select_rq_mask,    i), GFP_KERNEL, cpu_to_node(i));
+               zalloc_cpumask_var_node(&per_cpu(should_we_balance_tmpmask, i),
+                                       GFP_KERNEL, cpu_to_node(i));
 
 #ifdef CONFIG_CFS_BANDWIDTH
                INIT_CSD(&cpu_rq(i)->cfsb_csd, __cfsb_csd_unthrottle, cpu_rq(i));
index 342f58a329f528fcc6060208cfba9b7e908d3a98..5007b25c5bc653a9ca0696af1f7136150cd6131e 100644 (file)
@@ -373,6 +373,7 @@ EXPORT_SYMBOL_GPL(play_idle_precise);
 
 void cpu_startup_entry(enum cpuhp_state state)
 {
+       current->flags |= PF_IDLE;
        arch_cpu_idle_prepare();
        cpuhp_online_idle(state);
        while (1)
index 065e1ef8fc8d72e55c66000b7b25f9ba0189db45..95a7e1b7f1dab2d3e5eef4b16e2cefe7f25f2f22 100644 (file)
@@ -78,6 +78,7 @@ int task_work_add(struct task_struct *task, struct callback_head *work,
  * task_work_cancel_match - cancel a pending work added by task_work_add()
  * @task: the task which should execute the work
  * @match: match function to call
+ * @data: data to be passed in to match function
  *
  * RETURNS:
  * The found work or NULL if not found.
index a7264b2c17ad771d3bfc2a752da2339c157f4993..868008f56fec24fe7030d2fed9b063d1e1dd7926 100644 (file)
@@ -2853,6 +2853,17 @@ static int get_modules_for_addrs(struct module ***mods, unsigned long *addrs, u3
        return arr.mods_cnt;
 }
 
+static int addrs_check_error_injection_list(unsigned long *addrs, u32 cnt)
+{
+       u32 i;
+
+       for (i = 0; i < cnt; i++) {
+               if (!within_error_injection_list(addrs[i]))
+                       return -EINVAL;
+       }
+       return 0;
+}
+
 int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
 {
        struct bpf_kprobe_multi_link *link = NULL;
@@ -2930,6 +2941,11 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
                        goto error;
        }
 
+       if (prog->kprobe_override && addrs_check_error_injection_list(addrs, cnt)) {
+               err = -EINVAL;
+               goto error;
+       }
+
        link = kzalloc(sizeof(*link), GFP_KERNEL);
        if (!link) {
                err = -ENOMEM;
@@ -3207,8 +3223,10 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
                rcu_read_lock();
                task = get_pid_task(find_vpid(pid), PIDTYPE_PID);
                rcu_read_unlock();
-               if (!task)
+               if (!task) {
+                       err = -ESRCH;
                        goto error_path_put;
+               }
        }
 
        err = -ENOMEM;
index 78502d4c7214e8b97e2cc11c2072de47f91899cc..28daf0ce95c5112c62d3bf7de363f7a118c42d9b 100644 (file)
@@ -354,6 +354,11 @@ static void rb_init_page(struct buffer_data_page *bpage)
        local_set(&bpage->commit, 0);
 }
 
+static __always_inline unsigned int rb_page_commit(struct buffer_page *bpage)
+{
+       return local_read(&bpage->page->commit);
+}
+
 static void free_buffer_page(struct buffer_page *bpage)
 {
        free_page((unsigned long)bpage->page);
@@ -2003,7 +2008,7 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned long nr_pages)
                         * Increment overrun to account for the lost events.
                         */
                        local_add(page_entries, &cpu_buffer->overrun);
-                       local_sub(BUF_PAGE_SIZE, &cpu_buffer->entries_bytes);
+                       local_sub(rb_page_commit(to_remove_page), &cpu_buffer->entries_bytes);
                        local_inc(&cpu_buffer->pages_lost);
                }
 
@@ -2198,6 +2203,8 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
                                err = -ENOMEM;
                                goto out_err;
                        }
+
+                       cond_resched();
                }
 
                cpus_read_lock();
@@ -2365,11 +2372,6 @@ rb_reader_event(struct ring_buffer_per_cpu *cpu_buffer)
                               cpu_buffer->reader_page->read);
 }
 
-static __always_inline unsigned rb_page_commit(struct buffer_page *bpage)
-{
-       return local_read(&bpage->page->commit);
-}
-
 static struct ring_buffer_event *
 rb_iter_head_event(struct ring_buffer_iter *iter)
 {
@@ -2388,6 +2390,11 @@ rb_iter_head_event(struct ring_buffer_iter *iter)
         */
        commit = rb_page_commit(iter_head_page);
        smp_rmb();
+
+       /* An event needs to be at least 8 bytes in size */
+       if (iter->head > commit - 8)
+               goto reset;
+
        event = __rb_page_index(iter_head_page, iter->head);
        length = rb_event_length(event);
 
@@ -2510,7 +2517,7 @@ rb_handle_head_page(struct ring_buffer_per_cpu *cpu_buffer,
                 * the counters.
                 */
                local_add(entries, &cpu_buffer->overrun);
-               local_sub(BUF_PAGE_SIZE, &cpu_buffer->entries_bytes);
+               local_sub(rb_page_commit(next_page), &cpu_buffer->entries_bytes);
                local_inc(&cpu_buffer->pages_lost);
 
                /*
@@ -2653,9 +2660,6 @@ rb_reset_tail(struct ring_buffer_per_cpu *cpu_buffer,
 
        event = __rb_page_index(tail_page, tail);
 
-       /* account for padding bytes */
-       local_add(BUF_PAGE_SIZE - tail, &cpu_buffer->entries_bytes);
-
        /*
         * Save the original length to the meta data.
         * This will be used by the reader to add lost event
@@ -2669,7 +2673,8 @@ rb_reset_tail(struct ring_buffer_per_cpu *cpu_buffer,
         * write counter enough to allow another writer to slip
         * in on this page.
         * We put in a discarded commit instead, to make sure
-        * that this space is not used again.
+        * that this space is not used again, and this space will
+        * not be accounted into 'entries_bytes'.
         *
         * If we are less than the minimum size, we don't need to
         * worry about it.
@@ -2694,6 +2699,9 @@ rb_reset_tail(struct ring_buffer_per_cpu *cpu_buffer,
        /* time delta must be non zero */
        event->time_delta = 1;
 
+       /* account for padding bytes */
+       local_add(BUF_PAGE_SIZE - tail, &cpu_buffer->entries_bytes);
+
        /* Make sure the padding is visible before the tail_page->write update */
        smp_wmb();
 
@@ -4208,7 +4216,7 @@ u64 ring_buffer_oldest_event_ts(struct trace_buffer *buffer, int cpu)
 EXPORT_SYMBOL_GPL(ring_buffer_oldest_event_ts);
 
 /**
- * ring_buffer_bytes_cpu - get the number of bytes consumed in a cpu buffer
+ * ring_buffer_bytes_cpu - get the number of bytes unconsumed in a cpu buffer
  * @buffer: The ring buffer
  * @cpu: The per CPU buffer to read from.
  */
@@ -4716,6 +4724,7 @@ static void rb_advance_reader(struct ring_buffer_per_cpu *cpu_buffer)
 
        length = rb_event_length(event);
        cpu_buffer->reader_page->read += length;
+       cpu_buffer->read_bytes += length;
 }
 
 static void rb_advance_iter(struct ring_buffer_iter *iter)
@@ -5809,7 +5818,7 @@ int ring_buffer_read_page(struct trace_buffer *buffer,
        } else {
                /* update the entry counter */
                cpu_buffer->read += rb_page_entries(reader);
-               cpu_buffer->read_bytes += BUF_PAGE_SIZE;
+               cpu_buffer->read_bytes += rb_page_commit(reader);
 
                /* swap the pages */
                rb_init_page(bpage);
index 2b4ded75336706dc6650c7420d0c8972ac4910db..abaaf516fcae9ba9d510808ad13ad97e70cbcc07 100644 (file)
@@ -1772,7 +1772,7 @@ static void trace_create_maxlat_file(struct trace_array *tr,
        init_irq_work(&tr->fsnotify_irqwork, latency_fsnotify_workfn_irq);
        tr->d_max_latency = trace_create_file("tracing_max_latency",
                                              TRACE_MODE_WRITE,
-                                             d_tracer, &tr->max_latency,
+                                             d_tracer, tr,
                                              &tracing_max_lat_fops);
 }
 
@@ -1805,7 +1805,7 @@ void latency_fsnotify(struct trace_array *tr)
 
 #define trace_create_maxlat_file(tr, d_tracer)                         \
        trace_create_file("tracing_max_latency", TRACE_MODE_WRITE,      \
-                         d_tracer, &tr->max_latency, &tracing_max_lat_fops)
+                         d_tracer, tr, &tracing_max_lat_fops)
 
 #endif
 
@@ -4973,6 +4973,33 @@ int tracing_open_generic_tr(struct inode *inode, struct file *filp)
        return 0;
 }
 
+/*
+ * The private pointer of the inode is the trace_event_file.
+ * Update the tr ref count associated to it.
+ */
+int tracing_open_file_tr(struct inode *inode, struct file *filp)
+{
+       struct trace_event_file *file = inode->i_private;
+       int ret;
+
+       ret = tracing_check_open_get_tr(file->tr);
+       if (ret)
+               return ret;
+
+       filp->private_data = inode->i_private;
+
+       return 0;
+}
+
+int tracing_release_file_tr(struct inode *inode, struct file *filp)
+{
+       struct trace_event_file *file = inode->i_private;
+
+       trace_array_put(file->tr);
+
+       return 0;
+}
+
 static int tracing_mark_open(struct inode *inode, struct file *filp)
 {
        stream_open(inode, filp);
@@ -6691,14 +6718,18 @@ static ssize_t
 tracing_max_lat_read(struct file *filp, char __user *ubuf,
                     size_t cnt, loff_t *ppos)
 {
-       return tracing_nsecs_read(filp->private_data, ubuf, cnt, ppos);
+       struct trace_array *tr = filp->private_data;
+
+       return tracing_nsecs_read(&tr->max_latency, ubuf, cnt, ppos);
 }
 
 static ssize_t
 tracing_max_lat_write(struct file *filp, const char __user *ubuf,
                      size_t cnt, loff_t *ppos)
 {
-       return tracing_nsecs_write(filp->private_data, ubuf, cnt, ppos);
+       struct trace_array *tr = filp->private_data;
+
+       return tracing_nsecs_write(&tr->max_latency, ubuf, cnt, ppos);
 }
 
 #endif
@@ -7752,18 +7783,20 @@ static const struct file_operations tracing_thresh_fops = {
 
 #ifdef CONFIG_TRACER_MAX_TRACE
 static const struct file_operations tracing_max_lat_fops = {
-       .open           = tracing_open_generic,
+       .open           = tracing_open_generic_tr,
        .read           = tracing_max_lat_read,
        .write          = tracing_max_lat_write,
        .llseek         = generic_file_llseek,
+       .release        = tracing_release_generic_tr,
 };
 #endif
 
 static const struct file_operations set_tracer_fops = {
-       .open           = tracing_open_generic,
+       .open           = tracing_open_generic_tr,
        .read           = tracing_set_trace_read,
        .write          = tracing_set_trace_write,
        .llseek         = generic_file_llseek,
+       .release        = tracing_release_generic_tr,
 };
 
 static const struct file_operations tracing_pipe_fops = {
@@ -8956,12 +8989,33 @@ trace_options_write(struct file *filp, const char __user *ubuf, size_t cnt,
        return cnt;
 }
 
+static int tracing_open_options(struct inode *inode, struct file *filp)
+{
+       struct trace_option_dentry *topt = inode->i_private;
+       int ret;
+
+       ret = tracing_check_open_get_tr(topt->tr);
+       if (ret)
+               return ret;
+
+       filp->private_data = inode->i_private;
+       return 0;
+}
+
+static int tracing_release_options(struct inode *inode, struct file *file)
+{
+       struct trace_option_dentry *topt = file->private_data;
+
+       trace_array_put(topt->tr);
+       return 0;
+}
 
 static const struct file_operations trace_options_fops = {
-       .open = tracing_open_generic,
+       .open = tracing_open_options,
        .read = trace_options_read,
        .write = trace_options_write,
        .llseek = generic_file_llseek,
+       .release = tracing_release_options,
 };
 
 /*
@@ -9739,8 +9793,8 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
                          tr, &tracing_mark_fops);
 
        file = __find_event_file(tr, "ftrace", "print");
-       if (file && file->dir)
-               trace_create_file("trigger", TRACE_MODE_WRITE, file->dir,
+       if (file && file->ef)
+               eventfs_add_file("trigger", TRACE_MODE_WRITE, file->ef,
                                  file, &event_trigger_fops);
        tr->trace_marker_file = file;
 
index 5669dd1f90d9e828dacaa2f53e2b2259fc2ac1e0..77debe53f07cf5663f8421214c613505a584a314 100644 (file)
@@ -610,6 +610,8 @@ void tracing_reset_all_online_cpus(void);
 void tracing_reset_all_online_cpus_unlocked(void);
 int tracing_open_generic(struct inode *inode, struct file *filp);
 int tracing_open_generic_tr(struct inode *inode, struct file *filp);
+int tracing_open_file_tr(struct inode *inode, struct file *filp);
+int tracing_release_file_tr(struct inode *inode, struct file *filp);
 bool tracing_is_disabled(void);
 bool tracer_tracing_is_on(struct trace_array *tr);
 void tracer_tracing_on(struct trace_array *tr);
index ed367d713be07bca5e002cd5cb940b8d1a755480..91951d038ba491fe51ba66f7ed792526be0ed9d7 100644 (file)
@@ -992,19 +992,6 @@ static void remove_subsystem(struct trace_subsystem_dir *dir)
 
 static void remove_event_file_dir(struct trace_event_file *file)
 {
-       struct dentry *dir = file->dir;
-       struct dentry *child;
-
-       if (dir) {
-               spin_lock(&dir->d_lock);        /* probably unneeded */
-               list_for_each_entry(child, &dir->d_subdirs, d_child) {
-                       if (d_really_is_positive(child))        /* probably unneeded */
-                               d_inode(child)->i_private = NULL;
-               }
-               spin_unlock(&dir->d_lock);
-
-               tracefs_remove(dir);
-       }
        eventfs_remove(file->ef);
        list_del(&file->list);
        remove_subsystem(file->system);
@@ -2103,9 +2090,10 @@ static const struct file_operations ftrace_set_event_notrace_pid_fops = {
 };
 
 static const struct file_operations ftrace_enable_fops = {
-       .open = tracing_open_generic,
+       .open = tracing_open_file_tr,
        .read = event_enable_read,
        .write = event_enable_write,
+       .release = tracing_release_file_tr,
        .llseek = default_llseek,
 };
 
@@ -2122,9 +2110,10 @@ static const struct file_operations ftrace_event_id_fops = {
 };
 
 static const struct file_operations ftrace_event_filter_fops = {
-       .open = tracing_open_generic,
+       .open = tracing_open_file_tr,
        .read = event_filter_read,
        .write = event_filter_write,
+       .release = tracing_release_file_tr,
        .llseek = default_llseek,
 };
 
@@ -2297,6 +2286,7 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
 {
        struct event_subsystem *system, *iter;
        struct trace_subsystem_dir *dir;
+       struct eventfs_file *ef;
        int res;
 
        /* First see if we did not already create this dir */
@@ -2329,13 +2319,14 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
        } else
                __get_system(system);
 
-       dir->ef = eventfs_add_subsystem_dir(name, parent);
-       if (IS_ERR(dir->ef)) {
+       ef = eventfs_add_subsystem_dir(name, parent);
+       if (IS_ERR(ef)) {
                pr_warn("Failed to create system directory %s\n", name);
                __put_system(system);
                goto out_free;
        }
 
+       dir->ef = ef;
        dir->tr = tr;
        dir->ref_count = 1;
        dir->nr_events = 1;
@@ -2415,6 +2406,7 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file)
        struct trace_event_call *call = file->event_call;
        struct eventfs_file *ef_subsystem = NULL;
        struct trace_array *tr = file->tr;
+       struct eventfs_file *ef;
        const char *name;
        int ret;
 
@@ -2431,12 +2423,14 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file)
                return -ENOMEM;
 
        name = trace_event_name(call);
-       file->ef = eventfs_add_dir(name, ef_subsystem);
-       if (IS_ERR(file->ef)) {
+       ef = eventfs_add_dir(name, ef_subsystem);
+       if (IS_ERR(ef)) {
                pr_warn("Could not create tracefs '%s' directory\n", name);
                return -1;
        }
 
+       file->ef = ef;
+
        if (call->class->reg && !(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE))
                eventfs_add_file("enable", TRACE_MODE_WRITE, file->ef, file,
                                  &ftrace_enable_fops);
index abe805d471eb82e22d66f09573bd5f28ec8b2def..8650562bdaa9886e59a519aec516fc4b9209f0b5 100644 (file)
@@ -328,7 +328,8 @@ event_inject_read(struct file *file, char __user *buf, size_t size,
 }
 
 const struct file_operations event_inject_fops = {
-       .open = tracing_open_generic,
+       .open = tracing_open_file_tr,
        .read = event_inject_read,
        .write = event_inject_write,
+       .release = tracing_release_file_tr,
 };
index 9897d0bfcab7101a54c4dd01a698d505dcb74d90..14cb275a0bab01ba4e816af6e4df810aa830bee5 100644 (file)
@@ -337,7 +337,7 @@ static void print_synth_event_num_val(struct trace_seq *s,
                break;
 
        default:
-               trace_seq_printf(s, print_fmt, name, val, space);
+               trace_seq_printf(s, print_fmt, name, val->as_u64, space);
                break;
        }
 }
index 1a19a0a93dc1cb8931c2f9f5d512650a5a1a0fe6..e28db8e3b58c8154ef571b5359cab90b32f6acba 100644 (file)
@@ -28,7 +28,7 @@ static int count_argc(const char *str)
 
 /**
  * argv_free - free an argv
- * @argv - the argument vector to be freed
+ * @argv: the argument vector to be freed
  *
  * Frees an argv and the strings it points to.
  */
@@ -46,7 +46,7 @@ EXPORT_SYMBOL(argv_free);
  * @str: the string to be split
  * @argcp: returned argument count
  *
- * Returns an array of pointers to strings which are split out from
+ * Returns: an array of pointers to strings which are split out from
  * @str.  This is performed by strictly splitting on white-space; no
  * quote processing is performed.  Multiple whitespace characters are
  * considered to be a single argument separator.  The returned array
index 5181aa2e760b641f48575e5603db75679b6f04d3..a6348489d45fe8f9f6937069c56ce7978d971486 100644 (file)
@@ -65,7 +65,7 @@ struct kunit_glob_filter {
 };
 
 /* Split "suite_glob.test_glob" into two. Assumes filter_glob is not empty. */
-static void kunit_parse_glob_filter(struct kunit_glob_filter *parsed,
+static int kunit_parse_glob_filter(struct kunit_glob_filter *parsed,
                                    const char *filter_glob)
 {
        const int len = strlen(filter_glob);
@@ -73,16 +73,28 @@ static void kunit_parse_glob_filter(struct kunit_glob_filter *parsed,
 
        if (!period) {
                parsed->suite_glob = kzalloc(len + 1, GFP_KERNEL);
+               if (!parsed->suite_glob)
+                       return -ENOMEM;
+
                parsed->test_glob = NULL;
                strcpy(parsed->suite_glob, filter_glob);
-               return;
+               return 0;
        }
 
        parsed->suite_glob = kzalloc(period - filter_glob + 1, GFP_KERNEL);
+       if (!parsed->suite_glob)
+               return -ENOMEM;
+
        parsed->test_glob = kzalloc(len - (period - filter_glob) + 1, GFP_KERNEL);
+       if (!parsed->test_glob) {
+               kfree(parsed->suite_glob);
+               return -ENOMEM;
+       }
 
        strncpy(parsed->suite_glob, filter_glob, period - filter_glob);
        strncpy(parsed->test_glob, period + 1, len - (period - filter_glob));
+
+       return 0;
 }
 
 /* Create a copy of suite with only tests that match test_glob. */
@@ -152,21 +164,24 @@ kunit_filter_suites(const struct kunit_suite_set *suite_set,
        }
        copy_start = copy;
 
-       if (filter_glob)
-               kunit_parse_glob_filter(&parsed_glob, filter_glob);
+       if (filter_glob) {
+               *err = kunit_parse_glob_filter(&parsed_glob, filter_glob);
+               if (*err)
+                       goto free_copy;
+       }
 
        /* Parse attribute filters */
        if (filters) {
                filter_count = kunit_get_filter_count(filters);
                parsed_filters = kcalloc(filter_count, sizeof(*parsed_filters), GFP_KERNEL);
                if (!parsed_filters) {
-                       kfree(copy);
-                       return filtered;
+                       *err = -ENOMEM;
+                       goto free_parsed_glob;
                }
                for (j = 0; j < filter_count; j++)
                        parsed_filters[j] = kunit_next_attr_filter(&filters, err);
                if (*err)
-                       goto err;
+                       goto free_parsed_filters;
        }
 
        for (i = 0; &suite_set->start[i] != suite_set->end; i++) {
@@ -178,7 +193,7 @@ kunit_filter_suites(const struct kunit_suite_set *suite_set,
                                        parsed_glob.test_glob);
                        if (IS_ERR(filtered_suite)) {
                                *err = PTR_ERR(filtered_suite);
-                               goto err;
+                               goto free_parsed_filters;
                        }
                }
                if (filter_count > 0 && parsed_filters != NULL) {
@@ -195,10 +210,11 @@ kunit_filter_suites(const struct kunit_suite_set *suite_set,
                                filtered_suite = new_filtered_suite;
 
                                if (*err)
-                                       goto err;
+                                       goto free_parsed_filters;
+
                                if (IS_ERR(filtered_suite)) {
                                        *err = PTR_ERR(filtered_suite);
-                                       goto err;
+                                       goto free_parsed_filters;
                                }
                                if (!filtered_suite)
                                        break;
@@ -213,17 +229,19 @@ kunit_filter_suites(const struct kunit_suite_set *suite_set,
        filtered.start = copy_start;
        filtered.end = copy;
 
-err:
-       if (*err)
-               kfree(copy);
+free_parsed_filters:
+       if (filter_count)
+               kfree(parsed_filters);
 
+free_parsed_glob:
        if (filter_glob) {
                kfree(parsed_glob.suite_glob);
                kfree(parsed_glob.test_glob);
        }
 
-       if (filter_count)
-               kfree(parsed_filters);
+free_copy:
+       if (*err)
+               kfree(copy);
 
        return filtered;
 }
index 4084071d0eb5b77ff7066e63df1263f980a29afb..b4f6f96b28445fb62a2ff856def2d9a7877fa236 100644 (file)
@@ -119,7 +119,7 @@ static void parse_filter_attr_test(struct kunit *test)
 {
        int j, filter_count;
        struct kunit_attr_filter *parsed_filters;
-       char *filters = "speed>slow, module!=example";
+       char filters[] = "speed>slow, module!=example", *filter = filters;
        int err = 0;
 
        filter_count = kunit_get_filter_count(filters);
@@ -128,7 +128,7 @@ static void parse_filter_attr_test(struct kunit *test)
        parsed_filters = kunit_kcalloc(test, filter_count, sizeof(*parsed_filters),
                        GFP_KERNEL);
        for (j = 0; j < filter_count; j++) {
-               parsed_filters[j] = kunit_next_attr_filter(&filters, &err);
+               parsed_filters[j] = kunit_next_attr_filter(&filter, &err);
                KUNIT_ASSERT_EQ_MSG(test, err, 0, "failed to parse filter '%s'", filters[j]);
        }
 
@@ -154,6 +154,7 @@ static void filter_attr_test(struct kunit *test)
                .start = subsuite, .end = &subsuite[2],
        };
        struct kunit_suite_set got;
+       char filter[] = "speed>slow";
        int err = 0;
 
        subsuite[0] = alloc_fake_suite(test, "normal_suite", dummy_attr_test_cases);
@@ -168,7 +169,7 @@ static void filter_attr_test(struct kunit *test)
         * attribute is unset and thus, the filtering is based on the parent attribute
         * of slow.
         */
-       got = kunit_filter_suites(&suite_set, NULL, "speed>slow", NULL, &err);
+       got = kunit_filter_suites(&suite_set, NULL, filter, NULL, &err);
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start);
        KUNIT_ASSERT_EQ(test, err, 0);
        kfree_at_end(test, got.start);
@@ -191,12 +192,13 @@ static void filter_attr_empty_test(struct kunit *test)
                .start = subsuite, .end = &subsuite[2],
        };
        struct kunit_suite_set got;
+       char filter[] = "module!=dummy";
        int err = 0;
 
        subsuite[0] = alloc_fake_suite(test, "suite1", dummy_attr_test_cases);
        subsuite[1] = alloc_fake_suite(test, "suite2", dummy_attr_test_cases);
 
-       got = kunit_filter_suites(&suite_set, NULL, "module!=dummy", NULL, &err);
+       got = kunit_filter_suites(&suite_set, NULL, filter, NULL, &err);
        KUNIT_ASSERT_EQ(test, err, 0);
        kfree_at_end(test, got.start); /* just in case */
 
@@ -211,12 +213,13 @@ static void filter_attr_skip_test(struct kunit *test)
                .start = subsuite, .end = &subsuite[1],
        };
        struct kunit_suite_set got;
+       char filter[] = "speed>slow";
        int err = 0;
 
        subsuite[0] = alloc_fake_suite(test, "suite", dummy_attr_test_cases);
 
        /* Want: suite(slow, normal), NULL -> suite(slow with SKIP, normal), NULL */
-       got = kunit_filter_suites(&suite_set, NULL, "speed>slow", "skip", &err);
+       got = kunit_filter_suites(&suite_set, NULL, filter, "skip", &err);
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start);
        KUNIT_ASSERT_EQ(test, err, 0);
        kfree_at_end(test, got.start);
index 49698a168437ad1507580106aae91cde6c12a0e1..421f13981412302d07552f95fa286f117e81c9c1 100644 (file)
@@ -784,12 +784,13 @@ static int kunit_module_notify(struct notifier_block *nb, unsigned long val,
 
        switch (val) {
        case MODULE_STATE_LIVE:
-               kunit_module_init(mod);
                break;
        case MODULE_STATE_GOING:
                kunit_module_exit(mod);
                break;
        case MODULE_STATE_COMING:
+               kunit_module_init(mod);
+               break;
        case MODULE_STATE_UNFORMED:
                break;
        }
index c65566b4dc662afff966b773b78631de185c8851..68b45c82c37a6981bb72cc79ab4c4fcac8e2e489 100644 (file)
@@ -265,7 +265,8 @@ EXPORT_SYMBOL(sg_free_table);
  * @table:     The sg table header to use
  * @nents:     Number of entries in sg list
  * @max_ents:  The maximum number of entries the allocator returns per call
- * @nents_first_chunk: Number of entries int the (preallocated) first
+ * @first_chunk: first SGL if preallocated (may be %NULL)
+ * @nents_first_chunk: Number of entries in the (preallocated) first
  *     scatterlist chunk, 0 means no such preallocated chunk provided by user
  * @gfp_mask:  GFP allocation mask
  * @alloc_fn:  Allocator to use
@@ -788,6 +789,7 @@ EXPORT_SYMBOL(__sg_page_iter_dma_next);
  * @miter: sg mapping iter to be started
  * @sgl: sg list to iterate over
  * @nents: number of sg entries
+ * @flags: sg iterator flags
  *
  * Description:
  *   Starts mapping iterator @miter.
index 582f5317ff717d8d9fa017d0395a3bda3628a1f6..4ea4387053e8ea9b64ae3a5a8935afd50b9ac1f5 100644 (file)
@@ -3475,13 +3475,11 @@ skip:
  */
 static vm_fault_t filemap_map_folio_range(struct vm_fault *vmf,
                        struct folio *folio, unsigned long start,
-                       unsigned long addr, unsigned int nr_pages)
+                       unsigned long addr, unsigned int nr_pages,
+                       unsigned int *mmap_miss)
 {
        vm_fault_t ret = 0;
-       struct vm_area_struct *vma = vmf->vma;
-       struct file *file = vma->vm_file;
        struct page *page = folio_page(folio, start);
-       unsigned int mmap_miss = READ_ONCE(file->f_ra.mmap_miss);
        unsigned int count = 0;
        pte_t *old_ptep = vmf->pte;
 
@@ -3489,8 +3487,7 @@ static vm_fault_t filemap_map_folio_range(struct vm_fault *vmf,
                if (PageHWPoison(page + count))
                        goto skip;
 
-               if (mmap_miss > 0)
-                       mmap_miss--;
+               (*mmap_miss)++;
 
                /*
                 * NOTE: If there're PTE markers, we'll leave them to be
@@ -3525,7 +3522,35 @@ skip:
        }
 
        vmf->pte = old_ptep;
-       WRITE_ONCE(file->f_ra.mmap_miss, mmap_miss);
+
+       return ret;
+}
+
+static vm_fault_t filemap_map_order0_folio(struct vm_fault *vmf,
+               struct folio *folio, unsigned long addr,
+               unsigned int *mmap_miss)
+{
+       vm_fault_t ret = 0;
+       struct page *page = &folio->page;
+
+       if (PageHWPoison(page))
+               return ret;
+
+       (*mmap_miss)++;
+
+       /*
+        * NOTE: If there're PTE markers, we'll leave them to be
+        * handled in the specific fault path, and it'll prohibit
+        * the fault-around logic.
+        */
+       if (!pte_none(ptep_get(vmf->pte)))
+               return ret;
+
+       if (vmf->address == addr)
+               ret = VM_FAULT_NOPAGE;
+
+       set_pte_range(vmf, folio, page, 1, addr);
+       folio_ref_inc(folio);
 
        return ret;
 }
@@ -3541,7 +3566,7 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf,
        XA_STATE(xas, &mapping->i_pages, start_pgoff);
        struct folio *folio;
        vm_fault_t ret = 0;
-       int nr_pages = 0;
+       unsigned int nr_pages = 0, mmap_miss = 0, mmap_miss_saved;
 
        rcu_read_lock();
        folio = next_uptodate_folio(&xas, mapping, end_pgoff);
@@ -3569,25 +3594,27 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf,
                end = folio->index + folio_nr_pages(folio) - 1;
                nr_pages = min(end, end_pgoff) - xas.xa_index + 1;
 
-               /*
-                * NOTE: If there're PTE markers, we'll leave them to be
-                * handled in the specific fault path, and it'll prohibit the
-                * fault-around logic.
-                */
-               if (!pte_none(ptep_get(vmf->pte)))
-                       goto unlock;
-
-               ret |= filemap_map_folio_range(vmf, folio,
-                               xas.xa_index - folio->index, addr, nr_pages);
+               if (!folio_test_large(folio))
+                       ret |= filemap_map_order0_folio(vmf,
+                                       folio, addr, &mmap_miss);
+               else
+                       ret |= filemap_map_folio_range(vmf, folio,
+                                       xas.xa_index - folio->index, addr,
+                                       nr_pages, &mmap_miss);
 
-unlock:
                folio_unlock(folio);
                folio_put(folio);
-               folio = next_uptodate_folio(&xas, mapping, end_pgoff);
-       } while (folio);
+       } while ((folio = next_uptodate_folio(&xas, mapping, end_pgoff)) != NULL);
        pte_unmap_unlock(vmf->pte, vmf->ptl);
 out:
        rcu_read_unlock();
+
+       mmap_miss_saved = READ_ONCE(file->f_ra.mmap_miss);
+       if (mmap_miss >= mmap_miss_saved)
+               WRITE_ONCE(file->f_ra.mmap_miss, 0);
+       else
+               WRITE_ONCE(file->f_ra.mmap_miss, mmap_miss_saved - mmap_miss);
+
        return ret;
 }
 EXPORT_SYMBOL(filemap_map_pages);
index f70e3d7a602e1e816abe7357793fcb16fdfa3f91..d37831b8511c611a43dbe6f0a1bea1ccf6e7c0e4 100644 (file)
@@ -291,7 +291,7 @@ struct kasan_stack_ring {
 
 #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)
 
-#ifndef __HAVE_ARCH_SHADOW_MAP
+#ifndef kasan_shadow_to_mem
 static inline const void *kasan_shadow_to_mem(const void *shadow_addr)
 {
        return (void *)(((unsigned long)shadow_addr - KASAN_SHADOW_OFFSET)
@@ -299,15 +299,13 @@ static inline const void *kasan_shadow_to_mem(const void *shadow_addr)
 }
 #endif
 
+#ifndef addr_has_metadata
 static __always_inline bool addr_has_metadata(const void *addr)
 {
-#ifdef __HAVE_ARCH_SHADOW_MAP
-       return (kasan_mem_to_shadow((void *)addr) != NULL);
-#else
        return (kasan_reset_tag(addr) >=
                kasan_shadow_to_mem((void *)KASAN_SHADOW_START));
-#endif
 }
+#endif
 
 /**
  * kasan_check_range - Check memory region, and report if invalid access.
index a4d3282493b60461a7cb8e275db27a8638c0c4a4..d13dde2f8b56eccd7553641b1e989eeeab092acd 100644 (file)
@@ -2555,7 +2555,7 @@ static unsigned long calculate_high_delay(struct mem_cgroup *memcg,
  * Scheduled by try_charge() to be executed from the userland return path
  * and reclaims memory over the high limit.
  */
-void mem_cgroup_handle_over_high(void)
+void mem_cgroup_handle_over_high(gfp_t gfp_mask)
 {
        unsigned long penalty_jiffies;
        unsigned long pflags;
@@ -2583,7 +2583,7 @@ retry_reclaim:
         */
        nr_reclaimed = reclaim_high(memcg,
                                    in_retry ? SWAP_CLUSTER_MAX : nr_pages,
-                                   GFP_KERNEL);
+                                   gfp_mask);
 
        /*
         * memory.high is breached and reclaim is unable to keep up. Throttle
@@ -2819,7 +2819,7 @@ done_restock:
        if (current->memcg_nr_pages_over_high > MEMCG_CHARGE_BATCH &&
            !(current->flags & PF_MEMALLOC) &&
            gfpflags_allow_blocking(gfp_mask)) {
-               mem_cgroup_handle_over_high();
+               mem_cgroup_handle_over_high(gfp_mask);
        }
        return 0;
 }
index 056478c106eec6894b26b57d847ca785cb6b2faa..382e81c33fc437f2e11e49a1f8a7d68e99e5c845 100644 (file)
@@ -715,7 +715,7 @@ static unsigned long move_vma(struct vm_area_struct *vma,
        }
 
        vma_iter_init(&vmi, mm, old_addr);
-       if (!do_vmi_munmap(&vmi, mm, old_addr, old_len, uf_unmap, false)) {
+       if (do_vmi_munmap(&vmi, mm, old_addr, old_len, uf_unmap, false) < 0) {
                /* OOM: unable to split vma, just get accounts right */
                if (vm_flags & VM_ACCOUNT && !(flags & MREMAP_DONTUNMAP))
                        vm_acct_memory(old_len >> PAGE_SHIFT);
index 0c5be12f9336367fa4e25f202038ec22d1d79c82..95546f3763021af4d86098fcb780a034e3e7b8b2 100644 (file)
@@ -2400,7 +2400,7 @@ void free_unref_page(struct page *page, unsigned int order)
        struct per_cpu_pages *pcp;
        struct zone *zone;
        unsigned long pfn = page_to_pfn(page);
-       int migratetype;
+       int migratetype, pcpmigratetype;
 
        if (!free_unref_page_prepare(page, pfn, order))
                return;
@@ -2408,24 +2408,24 @@ void free_unref_page(struct page *page, unsigned int order)
        /*
         * We only track unmovable, reclaimable and movable on pcp lists.
         * Place ISOLATE pages on the isolated list because they are being
-        * offlined but treat HIGHATOMIC as movable pages so we can get those
-        * areas back if necessary. Otherwise, we may have to free
+        * offlined but treat HIGHATOMIC and CMA as movable pages so we can
+        * get those areas back if necessary. Otherwise, we may have to free
         * excessively into the page allocator
         */
-       migratetype = get_pcppage_migratetype(page);
+       migratetype = pcpmigratetype = get_pcppage_migratetype(page);
        if (unlikely(migratetype >= MIGRATE_PCPTYPES)) {
                if (unlikely(is_migrate_isolate(migratetype))) {
                        free_one_page(page_zone(page), page, pfn, order, migratetype, FPI_NONE);
                        return;
                }
-               migratetype = MIGRATE_MOVABLE;
+               pcpmigratetype = MIGRATE_MOVABLE;
        }
 
        zone = page_zone(page);
        pcp_trylock_prepare(UP_flags);
        pcp = pcp_spin_trylock(zone->per_cpu_pageset);
        if (pcp) {
-               free_unref_page_commit(zone, pcp, page, migratetype, order);
+               free_unref_page_commit(zone, pcp, page, pcpmigratetype, order);
                pcp_spin_unlock(pcp);
        } else {
                free_one_page(zone, page, pfn, order, migratetype, FPI_NONE);
index 02e62fccc80d4973b6626988eed07ff2482980d1..69595d3418829f08d05829f3ad5166b7421a30fc 100644 (file)
@@ -4586,7 +4586,7 @@ static struct file_system_type shmem_fs_type = {
 #endif
        .kill_sb        = kill_litter_super,
 #ifdef CONFIG_SHMEM
-       .fs_flags       = FS_USERNS_MOUNT | FS_ALLOW_IDMAP | FS_MGTIME,
+       .fs_flags       = FS_USERNS_MOUNT | FS_ALLOW_IDMAP,
 #else
        .fs_flags       = FS_USERNS_MOUNT,
 #endif
index d3a9843a043d7a0a731c3d8d89396b2bf5513fa0..fdb666607f10ac748a59daf46189cd1cba158c43 100644 (file)
@@ -10,7 +10,7 @@ menuconfig HAMRADIO
          If you want to connect your Linux box to an amateur radio, answer Y
          here. You want to read <https://www.tapr.org/>
          and more specifically about AX.25 on Linux
-         <http://www.linux-ax25.org/>.
+         <https://linux-ax25.in-berlin.de>.
 
          Note that the answer to this question won't directly affect the
          kernel: saying N will just cause the configurator to skip all
@@ -61,7 +61,7 @@ config AX25_DAMA_SLAVE
          configuration. Linux cannot yet act as a DAMA server.  This option
          only compiles DAMA slave support into the kernel.  It still needs to
          be enabled at runtime.  For more about DAMA see
-         <http://www.linux-ax25.org>.  If unsure, say Y.
+         <https://linux-ax25.in-berlin.de>.  If unsure, say Y.
 
 # placeholder until implemented
 config AX25_DAMA_MASTER
@@ -87,9 +87,9 @@ config NETROM
          A comprehensive listing of all the software for Linux amateur radio
          users as well as information about how to configure an AX.25 port is
          contained in the Linux Ham Wiki, available from
-         <http://www.linux-ax25.org>. You also might want to check out the
-         file <file:Documentation/networking/ax25.rst>. More information about
-         digital amateur radio in general is on the WWW at
+         <https://linux-ax25.in-berlin.de>. You also might want to check out
+         the file <file:Documentation/networking/ax25.rst>. More information
+         about digital amateur radio in general is on the WWW at
          <https://www.tapr.org/>.
 
          To compile this driver as a module, choose M here: the
@@ -106,9 +106,9 @@ config ROSE
          A comprehensive listing of all the software for Linux amateur radio
          users as well as information about how to configure an AX.25 port is
          contained in the Linux Ham Wiki, available from
-         <http://www.linux-ax25.org>.  You also might want to check out the
-         file <file:Documentation/networking/ax25.rst>. More information about
-         digital amateur radio in general is on the WWW at
+         <https://linux-ax25.in-berlin.de>.  You also might want to check out
+         the file <file:Documentation/networking/ax25.rst>. More information
+         about digital amateur radio in general is on the WWW at
          <https://www.tapr.org/>.
 
          To compile this driver as a module, choose M here: the
index 9d7bc8b96b53a911d5add8d0b21736358441755f..7431f89e897b9549a0c35d9431e36b6de2e80022 100644 (file)
@@ -124,7 +124,7 @@ static int deliver_clone(const struct net_bridge_port *prev,
 
        skb = skb_clone(skb, GFP_ATOMIC);
        if (!skb) {
-               dev->stats.tx_dropped++;
+               DEV_STATS_INC(dev, tx_dropped);
                return -ENOMEM;
        }
 
@@ -268,7 +268,7 @@ static void maybe_deliver_addr(struct net_bridge_port *p, struct sk_buff *skb,
 
        skb = skb_copy(skb, GFP_ATOMIC);
        if (!skb) {
-               dev->stats.tx_dropped++;
+               DEV_STATS_INC(dev, tx_dropped);
                return;
        }
 
index c34a0b0901b07de9e2a3f172527a2bf1c0b6f0b7..c729528b5e85f3a28eff6bd346c18bc11288e7a8 100644 (file)
@@ -181,12 +181,12 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
                        if ((mdst && mdst->host_joined) ||
                            br_multicast_is_router(brmctx, skb)) {
                                local_rcv = true;
-                               br->dev->stats.multicast++;
+                               DEV_STATS_INC(br->dev, multicast);
                        }
                        mcast_hit = true;
                } else {
                        local_rcv = true;
-                       br->dev->stats.multicast++;
+                       DEV_STATS_INC(br->dev, multicast);
                }
                break;
        case BR_PKT_UNICAST:
index ccff2b6ef9583eb2f284111b7294794779f7ba35..85df22f05c38b663f050410b9f7bcd32dd781951 100644 (file)
@@ -69,7 +69,7 @@
  */
 
 #include <linux/uaccess.h>
-#include <linux/bitops.h>
+#include <linux/bitmap.h>
 #include <linux/capability.h>
 #include <linux/cpu.h>
 #include <linux/types.h>
@@ -1080,7 +1080,7 @@ static int __dev_alloc_name(struct net *net, const char *name, char *buf)
                        return -EINVAL;
 
                /* Use one page as a bit array of possible slots */
-               inuse = (unsigned long *) get_zeroed_page(GFP_ATOMIC);
+               inuse = bitmap_zalloc(max_netdevices, GFP_ATOMIC);
                if (!inuse)
                        return -ENOMEM;
 
@@ -1109,7 +1109,7 @@ static int __dev_alloc_name(struct net *net, const char *name, char *buf)
                }
 
                i = find_first_zero_bit(inuse, max_netdevices);
-               free_page((unsigned long) inuse);
+               bitmap_free(inuse);
        }
 
        snprintf(buf, IFNAMSIZ, name, i);
index b3b3af0e78448ad399489f670a642eba12f8020c..272f09251343da46a1b3dbc6b1499c52c83d7725 100644 (file)
@@ -1446,7 +1446,7 @@ proto_again:
                        break;
                }
 
-               nhoff += ntohs(hdr->message_length);
+               nhoff += sizeof(struct ptp_header);
                fdret = FLOW_DISSECT_RET_OUT_GOOD;
                break;
        }
index 8f56e8723c7386c9f9344f1376823bfd0077c8c2..69453b936bd557c77a790a27ff64cc91e5a58296 100644 (file)
@@ -254,13 +254,8 @@ static int dccp_v4_err(struct sk_buff *skb, u32 info)
        int err;
        struct net *net = dev_net(skb->dev);
 
-       /* For the first __dccp_basic_hdr_len() check, we only need dh->dccph_x,
-        * which is in byte 7 of the dccp header.
-        * Our caller (icmp_socket_deliver()) already pulled 8 bytes for us.
-        *
-        * Later on, we want to access the sequence number fields, which are
-        * beyond 8 bytes, so we have to pskb_may_pull() ourselves.
-        */
+       if (!pskb_may_pull(skb, offset + sizeof(*dh)))
+               return -EINVAL;
        dh = (struct dccp_hdr *)(skb->data + offset);
        if (!pskb_may_pull(skb, offset + __dccp_basic_hdr_len(dh)))
                return -EINVAL;
index 33f6ccf6ba77b9bcc24054b09857aaee4bb71acf..c693a570682fba2ad93c7bceb8788bd9d51a0b41 100644 (file)
@@ -83,13 +83,8 @@ static int dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        __u64 seq;
        struct net *net = dev_net(skb->dev);
 
-       /* For the first __dccp_basic_hdr_len() check, we only need dh->dccph_x,
-        * which is in byte 7 of the dccp header.
-        * Our caller (icmpv6_notify()) already pulled 8 bytes for us.
-        *
-        * Later on, we want to access the sequence number fields, which are
-        * beyond 8 bytes, so we have to pskb_may_pull() ourselves.
-        */
+       if (!pskb_may_pull(skb, offset + sizeof(*dh)))
+               return -EINVAL;
        dh = (struct dccp_hdr *)(skb->data + offset);
        if (!pskb_may_pull(skb, offset + __dccp_basic_hdr_len(dh)))
                return -EINVAL;
index 6d37bab35c8fcc42e77d1fc081a87d61658751c3..16ed7bfd29e4fbf39e204278950834b9e69b9f97 100644 (file)
@@ -235,7 +235,7 @@ static void handshake_req_submit_test4(struct kunit *test)
        KUNIT_EXPECT_PTR_EQ(test, req, result);
 
        handshake_req_cancel(sock->sk);
-       sock_release(sock);
+       fput(filp);
 }
 
 static void handshake_req_submit_test5(struct kunit *test)
@@ -272,7 +272,7 @@ static void handshake_req_submit_test5(struct kunit *test)
        /* Assert */
        KUNIT_EXPECT_EQ(test, err, -EAGAIN);
 
-       sock_release(sock);
+       fput(filp);
        hn->hn_pending = saved;
 }
 
@@ -306,7 +306,7 @@ static void handshake_req_submit_test6(struct kunit *test)
        KUNIT_EXPECT_EQ(test, err, -EBUSY);
 
        handshake_req_cancel(sock->sk);
-       sock_release(sock);
+       fput(filp);
 }
 
 static void handshake_req_cancel_test1(struct kunit *test)
@@ -340,7 +340,7 @@ static void handshake_req_cancel_test1(struct kunit *test)
        /* Assert */
        KUNIT_EXPECT_TRUE(test, result);
 
-       sock_release(sock);
+       fput(filp);
 }
 
 static void handshake_req_cancel_test2(struct kunit *test)
@@ -382,7 +382,7 @@ static void handshake_req_cancel_test2(struct kunit *test)
        /* Assert */
        KUNIT_EXPECT_TRUE(test, result);
 
-       sock_release(sock);
+       fput(filp);
 }
 
 static void handshake_req_cancel_test3(struct kunit *test)
@@ -427,7 +427,7 @@ static void handshake_req_cancel_test3(struct kunit *test)
        /* Assert */
        KUNIT_EXPECT_FALSE(test, result);
 
-       sock_release(sock);
+       fput(filp);
 }
 
 static struct handshake_req *handshake_req_destroy_test;
@@ -471,7 +471,7 @@ static void handshake_req_destroy_test1(struct kunit *test)
        handshake_req_cancel(sock->sk);
 
        /* Act */
-       sock_release(sock);
+       fput(filp);
 
        /* Assert */
        KUNIT_EXPECT_PTR_EQ(test, handshake_req_destroy_test, req);
index 629daacc96071f40555939e590f9763c96553672..b71dab630a8732de385fb07694149d7e69a7151c 100644 (file)
@@ -594,6 +594,7 @@ static int fill_frame_info(struct hsr_frame_info *frame,
                proto = vlan_hdr->vlanhdr.h_vlan_encapsulated_proto;
                /* FIXME: */
                netdev_warn_once(skb->dev, "VLAN not yet supported");
+               return -EINVAL;
        }
 
        frame->is_from_san = false;
index b77f1189d19d1ff5dc76f4a7345efc7a65918399..6d14d935ee828d025d40ea237884d244cb56eb8e 100644 (file)
@@ -288,13 +288,13 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame)
 
        /* And leave the HSR tag. */
        if (ethhdr->h_proto == htons(ETH_P_HSR)) {
-               pull_size = sizeof(struct ethhdr);
+               pull_size = sizeof(struct hsr_tag);
                skb_pull(skb, pull_size);
                total_pull_size += pull_size;
        }
 
        /* And leave the HSR sup tag. */
-       pull_size = sizeof(struct hsr_tag);
+       pull_size = sizeof(struct hsr_sup_tag);
        skb_pull(skb, pull_size);
        total_pull_size += pull_size;
 
index 6851e33df7d14607034807c64ebe3a0b860af7f1..18e01791ad799d9562923d4359df2aafab2abd08 100644 (file)
@@ -83,7 +83,7 @@ struct hsr_vlan_ethhdr {
 struct hsr_sup_tlv {
        u8              HSR_TLV_type;
        u8              HSR_TLV_length;
-};
+} __packed;
 
 /* HSR/PRP Supervision Frame data types.
  * Field names as defined in the IEC:2010 standard for HSR.
index 9cf64ee47dd2b4fddf7be62c7110a1ad41b53fe8..ca0ff15dc8fa358b81a804eda7398ecd10f00743 100644 (file)
@@ -355,14 +355,14 @@ static void __inet_del_ifa(struct in_device *in_dev,
 {
        struct in_ifaddr *promote = NULL;
        struct in_ifaddr *ifa, *ifa1;
-       struct in_ifaddr *last_prim;
+       struct in_ifaddr __rcu **last_prim;
        struct in_ifaddr *prev_prom = NULL;
        int do_promote = IN_DEV_PROMOTE_SECONDARIES(in_dev);
 
        ASSERT_RTNL();
 
        ifa1 = rtnl_dereference(*ifap);
-       last_prim = rtnl_dereference(in_dev->ifa_list);
+       last_prim = ifap;
        if (in_dev->dead)
                goto no_promotions;
 
@@ -376,7 +376,7 @@ static void __inet_del_ifa(struct in_device *in_dev,
                while ((ifa = rtnl_dereference(*ifap1)) != NULL) {
                        if (!(ifa->ifa_flags & IFA_F_SECONDARY) &&
                            ifa1->ifa_scope <= ifa->ifa_scope)
-                               last_prim = ifa;
+                               last_prim = &ifa->ifa_next;
 
                        if (!(ifa->ifa_flags & IFA_F_SECONDARY) ||
                            ifa1->ifa_mask != ifa->ifa_mask ||
@@ -440,9 +440,9 @@ no_promotions:
 
                        rcu_assign_pointer(prev_prom->ifa_next, next_sec);
 
-                       last_sec = rtnl_dereference(last_prim->ifa_next);
+                       last_sec = rtnl_dereference(*last_prim);
                        rcu_assign_pointer(promote->ifa_next, last_sec);
-                       rcu_assign_pointer(last_prim->ifa_next, promote);
+                       rcu_assign_pointer(*last_prim, promote);
                }
 
                promote->ifa_flags &= ~IFA_F_SECONDARY;
index 7876b7d703cb5647086c45ca547c4caadc00c091..c32f5e28758be76d72cc33c754a10303e0905dbc 100644 (file)
@@ -815,41 +815,45 @@ static bool inet_bind2_bucket_match(const struct inet_bind2_bucket *tb,
                                    const struct net *net, unsigned short port,
                                    int l3mdev, const struct sock *sk)
 {
+       if (!net_eq(ib2_net(tb), net) || tb->port != port ||
+           tb->l3mdev != l3mdev)
+               return false;
+
 #if IS_ENABLED(CONFIG_IPV6)
-       if (sk->sk_family != tb->family)
+       if (sk->sk_family != tb->family) {
+               if (sk->sk_family == AF_INET)
+                       return ipv6_addr_v4mapped(&tb->v6_rcv_saddr) &&
+                               tb->v6_rcv_saddr.s6_addr32[3] == sk->sk_rcv_saddr;
+
                return false;
+       }
 
        if (sk->sk_family == AF_INET6)
-               return net_eq(ib2_net(tb), net) && tb->port == port &&
-                       tb->l3mdev == l3mdev &&
-                       ipv6_addr_equal(&tb->v6_rcv_saddr, &sk->sk_v6_rcv_saddr);
-       else
+               return ipv6_addr_equal(&tb->v6_rcv_saddr, &sk->sk_v6_rcv_saddr);
 #endif
-               return net_eq(ib2_net(tb), net) && tb->port == port &&
-                       tb->l3mdev == l3mdev && tb->rcv_saddr == sk->sk_rcv_saddr;
+       return tb->rcv_saddr == sk->sk_rcv_saddr;
 }
 
 bool inet_bind2_bucket_match_addr_any(const struct inet_bind2_bucket *tb, const struct net *net,
                                      unsigned short port, int l3mdev, const struct sock *sk)
 {
+       if (!net_eq(ib2_net(tb), net) || tb->port != port ||
+           tb->l3mdev != l3mdev)
+               return false;
+
 #if IS_ENABLED(CONFIG_IPV6)
        if (sk->sk_family != tb->family) {
                if (sk->sk_family == AF_INET)
-                       return net_eq(ib2_net(tb), net) && tb->port == port &&
-                               tb->l3mdev == l3mdev &&
-                               ipv6_addr_any(&tb->v6_rcv_saddr);
+                       return ipv6_addr_any(&tb->v6_rcv_saddr) ||
+                               ipv6_addr_v4mapped_any(&tb->v6_rcv_saddr);
 
                return false;
        }
 
        if (sk->sk_family == AF_INET6)
-               return net_eq(ib2_net(tb), net) && tb->port == port &&
-                       tb->l3mdev == l3mdev &&
-                       ipv6_addr_any(&tb->v6_rcv_saddr);
-       else
+               return ipv6_addr_any(&tb->v6_rcv_saddr);
 #endif
-               return net_eq(ib2_net(tb), net) && tb->port == port &&
-                       tb->l3mdev == l3mdev && tb->rcv_saddr == 0;
+       return tb->rcv_saddr == 0;
 }
 
 /* The socket's bhash2 hashbucket spinlock must be held when this is called */
index 66f419e7f9a7f3cab5328abb8c374686dccd2f19..a57062283219627e650bcac6985c0ab8a5bd4649 100644 (file)
@@ -1213,6 +1213,7 @@ EXPORT_INDIRECT_CALLABLE(ipv4_dst_check);
 
 static void ipv4_send_dest_unreach(struct sk_buff *skb)
 {
+       struct net_device *dev;
        struct ip_options opt;
        int res;
 
@@ -1230,7 +1231,8 @@ static void ipv4_send_dest_unreach(struct sk_buff *skb)
                opt.optlen = ip_hdr(skb)->ihl * 4 - sizeof(struct iphdr);
 
                rcu_read_lock();
-               res = __ip_options_compile(dev_net(skb->dev), &opt, skb, NULL);
+               dev = skb->dev ? skb->dev : skb_rtable(skb)->dst.dev;
+               res = __ip_options_compile(dev_net(dev), &opt, skb, NULL);
                rcu_read_unlock();
 
                if (res)
index 4580f61426bb8523638840069a50304994a873bf..dd1d8ffd5f5941a423a4ea43c1867709a101d0a0 100644 (file)
@@ -930,15 +930,18 @@ partial_message:
 out_error:
        kcm_push(kcm);
 
-       if (copied && sock->type == SOCK_SEQPACKET) {
+       if (sock->type == SOCK_SEQPACKET) {
                /* Wrote some bytes before encountering an
                 * error, return partial success.
                 */
-               goto partial_message;
-       }
-
-       if (head != kcm->seq_skb)
+               if (copied)
+                       goto partial_message;
+               if (head != kcm->seq_skb)
+                       kfree_skb(head);
+       } else {
                kfree_skb(head);
+               kcm->seq_skb = NULL;
+       }
 
        err = sk_stream_error(sk, msg->msg_flags, err);
 
index c254accb14dee6ef4b692c3f4bc96bfa161e2d84..cd15ec73073e05a133a3130f90e45e33394e759f 100644 (file)
@@ -1269,12 +1269,13 @@ static void mptcp_set_rwin(struct tcp_sock *tp, struct tcphdr *th)
 
                        if (rcv_wnd == rcv_wnd_old)
                                break;
-                       if (before64(rcv_wnd_new, rcv_wnd)) {
+
+                       rcv_wnd_old = rcv_wnd;
+                       if (before64(rcv_wnd_new, rcv_wnd_old)) {
                                MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_RCVWNDCONFLICTUPDATE);
                                goto raise_win;
                        }
                        MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_RCVWNDCONFLICT);
-                       rcv_wnd_old = rcv_wnd;
                }
                return;
        }
index a7fc16f5175d22a4e741c79edd84f1ea72c676bc..e252539b1e195416674f348856c1da20a8f2d2db 100644 (file)
@@ -405,7 +405,7 @@ drop:
        return false;
 }
 
-static void mptcp_stop_timer(struct sock *sk)
+static void mptcp_stop_rtx_timer(struct sock *sk)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
 
@@ -770,6 +770,46 @@ static bool __mptcp_ofo_queue(struct mptcp_sock *msk)
        return moved;
 }
 
+static bool __mptcp_subflow_error_report(struct sock *sk, struct sock *ssk)
+{
+       int err = sock_error(ssk);
+       int ssk_state;
+
+       if (!err)
+               return false;
+
+       /* only propagate errors on fallen-back sockets or
+        * on MPC connect
+        */
+       if (sk->sk_state != TCP_SYN_SENT && !__mptcp_check_fallback(mptcp_sk(sk)))
+               return false;
+
+       /* We need to propagate only transition to CLOSE state.
+        * Orphaned socket will see such state change via
+        * subflow_sched_work_if_closed() and that path will properly
+        * destroy the msk as needed.
+        */
+       ssk_state = inet_sk_state_load(ssk);
+       if (ssk_state == TCP_CLOSE && !sock_flag(sk, SOCK_DEAD))
+               inet_sk_state_store(sk, ssk_state);
+       WRITE_ONCE(sk->sk_err, -err);
+
+       /* This barrier is coupled with smp_rmb() in mptcp_poll() */
+       smp_wmb();
+       sk_error_report(sk);
+       return true;
+}
+
+void __mptcp_error_report(struct sock *sk)
+{
+       struct mptcp_subflow_context *subflow;
+       struct mptcp_sock *msk = mptcp_sk(sk);
+
+       mptcp_for_each_subflow(msk, subflow)
+               if (__mptcp_subflow_error_report(sk, mptcp_subflow_tcp_sock(subflow)))
+                       break;
+}
+
 /* In most cases we will be able to lock the mptcp socket.  If its already
  * owned, we need to defer to the work queue to avoid ABBA deadlock.
  */
@@ -852,6 +892,7 @@ static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk)
        mptcp_subflow_ctx(ssk)->subflow_id = msk->subflow_id++;
        mptcp_sockopt_sync_locked(msk, ssk);
        mptcp_subflow_joined(msk, ssk);
+       mptcp_stop_tout_timer(sk);
        return true;
 }
 
@@ -871,12 +912,12 @@ static void __mptcp_flush_join_list(struct sock *sk, struct list_head *join_list
        }
 }
 
-static bool mptcp_timer_pending(struct sock *sk)
+static bool mptcp_rtx_timer_pending(struct sock *sk)
 {
        return timer_pending(&inet_csk(sk)->icsk_retransmit_timer);
 }
 
-static void mptcp_reset_timer(struct sock *sk)
+static void mptcp_reset_rtx_timer(struct sock *sk)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
        unsigned long tout;
@@ -1010,10 +1051,10 @@ static void __mptcp_clean_una(struct sock *sk)
 out:
        if (snd_una == READ_ONCE(msk->snd_nxt) &&
            snd_una == READ_ONCE(msk->write_seq)) {
-               if (mptcp_timer_pending(sk) && !mptcp_data_fin_enabled(msk))
-                       mptcp_stop_timer(sk);
+               if (mptcp_rtx_timer_pending(sk) && !mptcp_data_fin_enabled(msk))
+                       mptcp_stop_rtx_timer(sk);
        } else {
-               mptcp_reset_timer(sk);
+               mptcp_reset_rtx_timer(sk);
        }
 }
 
@@ -1586,8 +1627,8 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
                mptcp_push_release(ssk, &info);
 
        /* ensure the rtx timer is running */
-       if (!mptcp_timer_pending(sk))
-               mptcp_reset_timer(sk);
+       if (!mptcp_rtx_timer_pending(sk))
+               mptcp_reset_rtx_timer(sk);
        if (do_check_data_fin)
                mptcp_check_send_data_fin(sk);
 }
@@ -1650,8 +1691,8 @@ out:
        if (copied) {
                tcp_push(ssk, 0, info.mss_now, tcp_sk(ssk)->nonagle,
                         info.size_goal);
-               if (!mptcp_timer_pending(sk))
-                       mptcp_reset_timer(sk);
+               if (!mptcp_rtx_timer_pending(sk))
+                       mptcp_reset_rtx_timer(sk);
 
                if (msk->snd_data_fin_enable &&
                    msk->snd_nxt + 1 == msk->write_seq)
@@ -2220,7 +2261,7 @@ static void mptcp_retransmit_timer(struct timer_list *t)
        sock_put(sk);
 }
 
-static void mptcp_timeout_timer(struct timer_list *t)
+static void mptcp_tout_timer(struct timer_list *t)
 {
        struct sock *sk = from_timer(sk, t, sk_timer);
 
@@ -2329,18 +2370,14 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
        bool dispose_it, need_push = false;
 
        /* If the first subflow moved to a close state before accept, e.g. due
-        * to an incoming reset, mptcp either:
-        * - if either the subflow or the msk are dead, destroy the context
-        *   (the subflow socket is deleted by inet_child_forget) and the msk
-        * - otherwise do nothing at the moment and take action at accept and/or
-        *   listener shutdown - user-space must be able to accept() the closed
-        *   socket.
+        * to an incoming reset or listener shutdown, the subflow socket is
+        * already deleted by inet_child_forget() and the mptcp socket can't
+        * survive too.
         */
-       if (msk->in_accept_queue && msk->first == ssk) {
-               if (!sock_flag(sk, SOCK_DEAD) && !sock_flag(ssk, SOCK_DEAD))
-                       return;
-
+       if (msk->in_accept_queue && msk->first == ssk &&
+           (sock_flag(sk, SOCK_DEAD) || sock_flag(ssk, SOCK_DEAD))) {
                /* ensure later check in mptcp_worker() will dispose the msk */
+               mptcp_set_close_tout(sk, tcp_jiffies32 - (TCP_TIMEWAIT_LEN + 1));
                sock_set_flag(sk, SOCK_DEAD);
                lock_sock_nested(ssk, SINGLE_DEPTH_NESTING);
                mptcp_subflow_drop_ctx(ssk);
@@ -2392,6 +2429,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
        }
 
 out_release:
+       __mptcp_subflow_error_report(sk, ssk);
        release_sock(ssk);
 
        sock_put(ssk);
@@ -2402,6 +2440,22 @@ out_release:
 out:
        if (need_push)
                __mptcp_push_pending(sk, 0);
+
+       /* Catch every 'all subflows closed' scenario, including peers silently
+        * closing them, e.g. due to timeout.
+        * For established sockets, allow an additional timeout before closing,
+        * as the protocol can still create more subflows.
+        */
+       if (list_is_singular(&msk->conn_list) && msk->first &&
+           inet_sk_state_load(msk->first) == TCP_CLOSE) {
+               if (sk->sk_state != TCP_ESTABLISHED ||
+                   msk->in_accept_queue || sock_flag(sk, SOCK_DEAD)) {
+                       inet_sk_state_store(sk, TCP_CLOSE);
+                       mptcp_close_wake_up(sk);
+               } else {
+                       mptcp_start_tout_timer(sk);
+               }
+       }
 }
 
 void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
@@ -2445,23 +2499,14 @@ static void __mptcp_close_subflow(struct sock *sk)
 
 }
 
-static bool mptcp_should_close(const struct sock *sk)
+static bool mptcp_close_tout_expired(const struct sock *sk)
 {
-       s32 delta = tcp_jiffies32 - inet_csk(sk)->icsk_mtup.probe_timestamp;
-       struct mptcp_subflow_context *subflow;
-
-       if (delta >= TCP_TIMEWAIT_LEN || mptcp_sk(sk)->in_accept_queue)
-               return true;
+       if (!inet_csk(sk)->icsk_mtup.probe_timestamp ||
+           sk->sk_state == TCP_CLOSE)
+               return false;
 
-       /* if all subflows are in closed status don't bother with additional
-        * timeout
-        */
-       mptcp_for_each_subflow(mptcp_sk(sk), subflow) {
-               if (inet_sk_state_load(mptcp_subflow_tcp_sock(subflow)) !=
-                   TCP_CLOSE)
-                       return false;
-       }
-       return true;
+       return time_after32(tcp_jiffies32,
+                 inet_csk(sk)->icsk_mtup.probe_timestamp + TCP_TIMEWAIT_LEN);
 }
 
 static void mptcp_check_fastclose(struct mptcp_sock *msk)
@@ -2588,27 +2633,28 @@ static void __mptcp_retrans(struct sock *sk)
 reset_timer:
        mptcp_check_and_set_pending(sk);
 
-       if (!mptcp_timer_pending(sk))
-               mptcp_reset_timer(sk);
+       if (!mptcp_rtx_timer_pending(sk))
+               mptcp_reset_rtx_timer(sk);
 }
 
 /* schedule the timeout timer for the relevant event: either close timeout
  * or mp_fail timeout. The close timeout takes precedence on the mp_fail one
  */
-void mptcp_reset_timeout(struct mptcp_sock *msk, unsigned long fail_tout)
+void mptcp_reset_tout_timer(struct mptcp_sock *msk, unsigned long fail_tout)
 {
        struct sock *sk = (struct sock *)msk;
        unsigned long timeout, close_timeout;
 
-       if (!fail_tout && !sock_flag(sk, SOCK_DEAD))
+       if (!fail_tout && !inet_csk(sk)->icsk_mtup.probe_timestamp)
                return;
 
-       close_timeout = inet_csk(sk)->icsk_mtup.probe_timestamp - tcp_jiffies32 + jiffies + TCP_TIMEWAIT_LEN;
+       close_timeout = inet_csk(sk)->icsk_mtup.probe_timestamp - tcp_jiffies32 + jiffies +
+                       TCP_TIMEWAIT_LEN;
 
        /* the close timeout takes precedence on the fail one, and here at least one of
         * them is active
         */
-       timeout = sock_flag(sk, SOCK_DEAD) ? close_timeout : fail_tout;
+       timeout = inet_csk(sk)->icsk_mtup.probe_timestamp ? close_timeout : fail_tout;
 
        sk_reset_timer(sk, &sk->sk_timer, timeout);
 }
@@ -2627,8 +2673,6 @@ static void mptcp_mp_fail_no_response(struct mptcp_sock *msk)
        mptcp_subflow_reset(ssk);
        WRITE_ONCE(mptcp_subflow_ctx(ssk)->fail_tout, 0);
        unlock_sock_fast(ssk, slow);
-
-       mptcp_reset_timeout(msk, 0);
 }
 
 static void mptcp_do_fastclose(struct sock *sk)
@@ -2665,18 +2709,14 @@ static void mptcp_worker(struct work_struct *work)
        if (test_and_clear_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
                __mptcp_close_subflow(sk);
 
-       /* There is no point in keeping around an orphaned sk timedout or
-        * closed, but we need the msk around to reply to incoming DATA_FIN,
-        * even if it is orphaned and in FIN_WAIT2 state
-        */
-       if (sock_flag(sk, SOCK_DEAD)) {
-               if (mptcp_should_close(sk))
-                       mptcp_do_fastclose(sk);
+       if (mptcp_close_tout_expired(sk)) {
+               mptcp_do_fastclose(sk);
+               mptcp_close_wake_up(sk);
+       }
 
-               if (sk->sk_state == TCP_CLOSE) {
-                       __mptcp_destroy_sock(sk);
-                       goto unlock;
-               }
+       if (sock_flag(sk, SOCK_DEAD) && sk->sk_state == TCP_CLOSE) {
+               __mptcp_destroy_sock(sk);
+               goto unlock;
        }
 
        if (test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags))
@@ -2717,7 +2757,7 @@ static void __mptcp_init_sock(struct sock *sk)
 
        /* re-use the csk retrans timer for MPTCP-level retrans */
        timer_setup(&msk->sk.icsk_retransmit_timer, mptcp_retransmit_timer, 0);
-       timer_setup(&sk->sk_timer, mptcp_timeout_timer, 0);
+       timer_setup(&sk->sk_timer, mptcp_tout_timer, 0);
 }
 
 static void mptcp_ca_reset(struct sock *sk)
@@ -2808,8 +2848,8 @@ void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how)
                } else {
                        pr_debug("Sending DATA_FIN on subflow %p", ssk);
                        tcp_send_ack(ssk);
-                       if (!mptcp_timer_pending(sk))
-                               mptcp_reset_timer(sk);
+                       if (!mptcp_rtx_timer_pending(sk))
+                               mptcp_reset_rtx_timer(sk);
                }
                break;
        }
@@ -2892,7 +2932,7 @@ static void __mptcp_destroy_sock(struct sock *sk)
 
        might_sleep();
 
-       mptcp_stop_timer(sk);
+       mptcp_stop_rtx_timer(sk);
        sk_stop_timer(sk, &sk->sk_timer);
        msk->pm.status = 0;
        mptcp_release_sched(msk);
@@ -2975,7 +3015,6 @@ bool __mptcp_close(struct sock *sk, long timeout)
 
 cleanup:
        /* orphan all the subflows */
-       inet_csk(sk)->icsk_mtup.probe_timestamp = tcp_jiffies32;
        mptcp_for_each_subflow(msk, subflow) {
                struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
                bool slow = lock_sock_fast_nested(ssk);
@@ -3012,7 +3051,7 @@ cleanup:
                __mptcp_destroy_sock(sk);
                do_cancel_work = true;
        } else {
-               mptcp_reset_timeout(msk, 0);
+               mptcp_start_tout_timer(sk);
        }
 
        return do_cancel_work;
@@ -3075,8 +3114,8 @@ static int mptcp_disconnect(struct sock *sk, int flags)
        mptcp_check_listen_stop(sk);
        inet_sk_state_store(sk, TCP_CLOSE);
 
-       mptcp_stop_timer(sk);
-       sk_stop_timer(sk, &sk->sk_timer);
+       mptcp_stop_rtx_timer(sk);
+       mptcp_stop_tout_timer(sk);
 
        if (msk->token)
                mptcp_event(MPTCP_EVENT_CLOSED, msk, NULL, GFP_KERNEL);
index 7254b35625756b24fbe33a2139add079ee98fd63..ed61d6850cce899195240a1eb15a2c03129bbb26 100644 (file)
@@ -718,7 +718,29 @@ void mptcp_get_options(const struct sk_buff *skb,
 
 void mptcp_finish_connect(struct sock *sk);
 void __mptcp_set_connected(struct sock *sk);
-void mptcp_reset_timeout(struct mptcp_sock *msk, unsigned long fail_tout);
+void mptcp_reset_tout_timer(struct mptcp_sock *msk, unsigned long fail_tout);
+
+static inline void mptcp_stop_tout_timer(struct sock *sk)
+{
+       if (!inet_csk(sk)->icsk_mtup.probe_timestamp)
+               return;
+
+       sk_stop_timer(sk, &sk->sk_timer);
+       inet_csk(sk)->icsk_mtup.probe_timestamp = 0;
+}
+
+static inline void mptcp_set_close_tout(struct sock *sk, unsigned long tout)
+{
+       /* avoid 0 timestamp, as that means no close timeout */
+       inet_csk(sk)->icsk_mtup.probe_timestamp = tout ? : 1;
+}
+
+static inline void mptcp_start_tout_timer(struct sock *sk)
+{
+       mptcp_set_close_tout(sk, tcp_jiffies32);
+       mptcp_reset_tout_timer(mptcp_sk(sk), 0);
+}
+
 static inline bool mptcp_is_fully_established(struct sock *sk)
 {
        return inet_sk_state_load(sk) == TCP_ESTABLISHED &&
index 9bf3c7bc1762a0990401f7e07db1e0f395f4e567..918c1a2357906312c1c8317fd0115df8f117079e 100644 (file)
@@ -1226,7 +1226,7 @@ static void mptcp_subflow_fail(struct mptcp_sock *msk, struct sock *ssk)
        WRITE_ONCE(subflow->fail_tout, fail_tout);
        tcp_send_ack(ssk);
 
-       mptcp_reset_timeout(msk, subflow->fail_tout);
+       mptcp_reset_tout_timer(msk, subflow->fail_tout);
 }
 
 static bool subflow_check_data_avail(struct sock *ssk)
@@ -1362,42 +1362,6 @@ void mptcp_space(const struct sock *ssk, int *space, int *full_space)
        *full_space = mptcp_win_from_space(sk, READ_ONCE(sk->sk_rcvbuf));
 }
 
-void __mptcp_error_report(struct sock *sk)
-{
-       struct mptcp_subflow_context *subflow;
-       struct mptcp_sock *msk = mptcp_sk(sk);
-
-       mptcp_for_each_subflow(msk, subflow) {
-               struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
-               int err = sock_error(ssk);
-               int ssk_state;
-
-               if (!err)
-                       continue;
-
-               /* only propagate errors on fallen-back sockets or
-                * on MPC connect
-                */
-               if (sk->sk_state != TCP_SYN_SENT && !__mptcp_check_fallback(msk))
-                       continue;
-
-               /* We need to propagate only transition to CLOSE state.
-                * Orphaned socket will see such state change via
-                * subflow_sched_work_if_closed() and that path will properly
-                * destroy the msk as needed.
-                */
-               ssk_state = inet_sk_state_load(ssk);
-               if (ssk_state == TCP_CLOSE && !sock_flag(sk, SOCK_DEAD))
-                       inet_sk_state_store(sk, ssk_state);
-               WRITE_ONCE(sk->sk_err, -err);
-
-               /* This barrier is coupled with smp_rmb() in mptcp_poll() */
-               smp_wmb();
-               sk_error_report(sk);
-               break;
-       }
-}
-
 static void subflow_error_report(struct sock *ssk)
 {
        struct sock *sk = mptcp_subflow_ctx(ssk)->conn;
@@ -1588,6 +1552,7 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
        mptcp_sock_graft(ssk, sk->sk_socket);
        iput(SOCK_INODE(sf));
        WRITE_ONCE(msk->allow_infinite_fallback, false);
+       mptcp_stop_tout_timer(sk);
        return 0;
 
 failed_unlink:
index 62fb1031763d14f82dcfee50191a21cb38ad8cf9..f8854bff286cbd7229e0c543689f892f40e80cab 100644 (file)
@@ -89,6 +89,11 @@ static int ncsi_aen_handler_lsc(struct ncsi_dev_priv *ndp,
        if ((had_link == has_link) || chained)
                return 0;
 
+       if (had_link)
+               netif_carrier_off(ndp->ndev.dev);
+       else
+               netif_carrier_on(ndp->ndev.dev);
+
        if (!ndp->multi_package && !nc->package->multi_channel) {
                if (had_link) {
                        ndp->flags |= NCSI_DEV_RESHUFFLE;
index e564b5174261159173bfda0756480ca554243b7d..35d2f9c9ada0252e01af3bee1faa1f63a0c94498 100644 (file)
@@ -682,6 +682,14 @@ __ip_set_put(struct ip_set *set)
 /* set->ref can be swapped out by ip_set_swap, netlink events (like dump) need
  * a separate reference counter
  */
+static void
+__ip_set_get_netlink(struct ip_set *set)
+{
+       write_lock_bh(&ip_set_ref_lock);
+       set->ref_netlink++;
+       write_unlock_bh(&ip_set_ref_lock);
+}
+
 static void
 __ip_set_put_netlink(struct ip_set *set)
 {
@@ -1693,11 +1701,11 @@ call_ad(struct net *net, struct sock *ctnl, struct sk_buff *skb,
 
        do {
                if (retried) {
-                       __ip_set_get(set);
+                       __ip_set_get_netlink(set);
                        nfnl_unlock(NFNL_SUBSYS_IPSET);
                        cond_resched();
                        nfnl_lock(NFNL_SUBSYS_IPSET);
-                       __ip_set_put(set);
+                       __ip_set_put_netlink(set);
                }
 
                ip_set_lock(set);
index c7a6114091ae59718f494f8bf10346f0632b761c..b21799d468d2815413cc1334cb6c5e5df7fe231d 100644 (file)
@@ -381,6 +381,8 @@ __bpf_kfunc struct nf_conn *bpf_ct_insert_entry(struct nf_conn___init *nfct_i)
        struct nf_conn *nfct = (struct nf_conn *)nfct_i;
        int err;
 
+       if (!nf_ct_is_confirmed(nfct))
+               nfct->timeout += nfct_time_stamp;
        nfct->status |= IPS_CONFIRMED;
        err = nf_conntrack_hash_check_insert(nfct);
        if (err < 0) {
index 0b513f7bf9f391e7f94a3b4ebce9d47a51fa6cb2..dd62cc12e7750734fec9be8a90fd0defcbc815e0 100644 (file)
@@ -40,10 +40,10 @@ static const u8 nf_ct_ext_type_len[NF_CT_EXT_NUM] = {
        [NF_CT_EXT_ECACHE] = sizeof(struct nf_conntrack_ecache),
 #endif
 #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
-       [NF_CT_EXT_TSTAMP] = sizeof(struct nf_conn_acct),
+       [NF_CT_EXT_TSTAMP] = sizeof(struct nf_conn_tstamp),
 #endif
 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
-       [NF_CT_EXT_TIMEOUT] = sizeof(struct nf_conn_tstamp),
+       [NF_CT_EXT_TIMEOUT] = sizeof(struct nf_conn_timeout),
 #endif
 #ifdef CONFIG_NF_CONNTRACK_LABELS
        [NF_CT_EXT_LABELS] = sizeof(struct nf_conn_labels),
index e429ebba74b3d13b441f8130087e81153ee1032c..4356189360fb88d695b25070264783520aeef6b1 100644 (file)
@@ -1219,6 +1219,10 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
             flags & NFT_TABLE_F_OWNER))
                return -EOPNOTSUPP;
 
+       /* No dormant off/on/off/on games in single transaction */
+       if (ctx->table->flags & __NFT_TABLE_F_UPDATE)
+               return -EINVAL;
+
        trans = nft_trans_alloc(ctx, NFT_MSG_NEWTABLE,
                                sizeof(struct nft_trans_table));
        if (trans == NULL)
@@ -1432,7 +1436,7 @@ static int nft_flush_table(struct nft_ctx *ctx)
                if (!nft_is_active_next(ctx->net, chain))
                        continue;
 
-               if (nft_chain_is_bound(chain))
+               if (nft_chain_binding(chain))
                        continue;
 
                ctx->chain = chain;
@@ -1446,8 +1450,7 @@ static int nft_flush_table(struct nft_ctx *ctx)
                if (!nft_is_active_next(ctx->net, set))
                        continue;
 
-               if (nft_set_is_anonymous(set) &&
-                   !list_empty(&set->bindings))
+               if (nft_set_is_anonymous(set))
                        continue;
 
                err = nft_delset(ctx, set);
@@ -1477,7 +1480,7 @@ static int nft_flush_table(struct nft_ctx *ctx)
                if (!nft_is_active_next(ctx->net, chain))
                        continue;
 
-               if (nft_chain_is_bound(chain))
+               if (nft_chain_binding(chain))
                        continue;
 
                ctx->chain = chain;
@@ -2910,6 +2913,9 @@ static int nf_tables_delchain(struct sk_buff *skb, const struct nfnl_info *info,
                return PTR_ERR(chain);
        }
 
+       if (nft_chain_binding(chain))
+               return -EOPNOTSUPP;
+
        nft_ctx_init(&ctx, net, skb, info->nlh, family, table, chain, nla);
 
        if (nla[NFTA_CHAIN_HOOK]) {
@@ -3449,6 +3455,8 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
        struct net *net = sock_net(skb->sk);
        const struct nft_rule *rule, *prule;
        unsigned int s_idx = cb->args[0];
+       unsigned int entries = 0;
+       int ret = 0;
        u64 handle;
 
        prule = NULL;
@@ -3471,9 +3479,11 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
                                        NFT_MSG_NEWRULE,
                                        NLM_F_MULTI | NLM_F_APPEND,
                                        table->family,
-                                       table, chain, rule, handle, reset) < 0)
-                       return 1;
-
+                                       table, chain, rule, handle, reset) < 0) {
+                       ret = 1;
+                       break;
+               }
+               entries++;
                nl_dump_check_consistent(cb, nlmsg_hdr(skb));
 cont:
                prule = rule;
@@ -3481,10 +3491,10 @@ cont_skip:
                (*idx)++;
        }
 
-       if (reset && *idx)
-               audit_log_rule_reset(table, cb->seq, *idx);
+       if (reset && entries)
+               audit_log_rule_reset(table, cb->seq, entries);
 
-       return 0;
+       return ret;
 }
 
 static int nf_tables_dump_rules(struct sk_buff *skb,
@@ -3971,6 +3981,11 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
        }
 
        if (info->nlh->nlmsg_flags & NLM_F_REPLACE) {
+               if (nft_chain_binding(chain)) {
+                       err = -EOPNOTSUPP;
+                       goto err_destroy_flow_rule;
+               }
+
                err = nft_delrule(&ctx, old_rule);
                if (err < 0)
                        goto err_destroy_flow_rule;
@@ -4078,7 +4093,7 @@ static int nf_tables_delrule(struct sk_buff *skb, const struct nfnl_info *info,
                        NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
                        return PTR_ERR(chain);
                }
-               if (nft_chain_is_bound(chain))
+               if (nft_chain_binding(chain))
                        return -EOPNOTSUPP;
        }
 
@@ -4112,7 +4127,7 @@ static int nf_tables_delrule(struct sk_buff *skb, const struct nfnl_info *info,
                list_for_each_entry(chain, &table->chains, list) {
                        if (!nft_is_active_next(net, chain))
                                continue;
-                       if (nft_chain_is_bound(chain))
+                       if (nft_chain_binding(chain))
                                continue;
 
                        ctx.chain = chain;
@@ -7183,8 +7198,10 @@ static int nf_tables_delsetelem(struct sk_buff *skb,
        if (IS_ERR(set))
                return PTR_ERR(set);
 
-       if (!list_empty(&set->bindings) &&
-           (set->flags & (NFT_SET_CONSTANT | NFT_SET_ANONYMOUS)))
+       if (nft_set_is_anonymous(set))
+               return -EOPNOTSUPP;
+
+       if (!list_empty(&set->bindings) && (set->flags & NFT_SET_CONSTANT))
                return -EBUSY;
 
        nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
@@ -9562,12 +9579,15 @@ static int nft_trans_gc_space(struct nft_trans_gc *trans)
 struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc,
                                              unsigned int gc_seq, gfp_t gfp)
 {
+       struct nft_set *set;
+
        if (nft_trans_gc_space(gc))
                return gc;
 
+       set = gc->set;
        nft_trans_gc_queue_work(gc);
 
-       return nft_trans_gc_alloc(gc->set, gc_seq, gfp);
+       return nft_trans_gc_alloc(set, gc_seq, gfp);
 }
 
 void nft_trans_gc_queue_async_done(struct nft_trans_gc *trans)
@@ -9582,15 +9602,18 @@ void nft_trans_gc_queue_async_done(struct nft_trans_gc *trans)
 
 struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp)
 {
+       struct nft_set *set;
+
        if (WARN_ON_ONCE(!lockdep_commit_lock_is_held(gc->net)))
                return NULL;
 
        if (nft_trans_gc_space(gc))
                return gc;
 
+       set = gc->set;
        call_rcu(&gc->rcu, nft_trans_gc_trans_free);
 
-       return nft_trans_gc_alloc(gc->set, 0, gfp);
+       return nft_trans_gc_alloc(set, 0, gfp);
 }
 
 void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans)
@@ -9605,8 +9628,9 @@ void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans)
        call_rcu(&trans->rcu, nft_trans_gc_trans_free);
 }
 
-struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
-                                          unsigned int gc_seq)
+static struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
+                                                 unsigned int gc_seq,
+                                                 bool sync)
 {
        struct nft_set_elem_catchall *catchall;
        const struct nft_set *set = gc->set;
@@ -9622,7 +9646,11 @@ struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
 
                nft_set_elem_dead(ext);
 dead_elem:
-               gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
+               if (sync)
+                       gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
+               else
+                       gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
+
                if (!gc)
                        return NULL;
 
@@ -9632,6 +9660,17 @@ dead_elem:
        return gc;
 }
 
+struct nft_trans_gc *nft_trans_gc_catchall_async(struct nft_trans_gc *gc,
+                                                unsigned int gc_seq)
+{
+       return nft_trans_gc_catchall(gc, gc_seq, false);
+}
+
+struct nft_trans_gc *nft_trans_gc_catchall_sync(struct nft_trans_gc *gc)
+{
+       return nft_trans_gc_catchall(gc, 0, true);
+}
+
 static void nf_tables_module_autoload_cleanup(struct net *net)
 {
        struct nftables_pernet *nft_net = nft_pernet(net);
@@ -11054,7 +11093,7 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
        ctx.family = table->family;
        ctx.table = table;
        list_for_each_entry(chain, &table->chains, list) {
-               if (nft_chain_is_bound(chain))
+               if (nft_chain_binding(chain))
                        continue;
 
                ctx.chain = chain;
index 524763659f2510c2678e013b19a12a929f7630c5..2013de934cef096ac8fa512c1cd4bc18c7c52c10 100644 (file)
@@ -338,12 +338,9 @@ static void nft_rhash_gc(struct work_struct *work)
 
        while ((he = rhashtable_walk_next(&hti))) {
                if (IS_ERR(he)) {
-                       if (PTR_ERR(he) != -EAGAIN) {
-                               nft_trans_gc_destroy(gc);
-                               gc = NULL;
-                               goto try_later;
-                       }
-                       continue;
+                       nft_trans_gc_destroy(gc);
+                       gc = NULL;
+                       goto try_later;
                }
 
                /* Ruleset has been updated, try later. */
@@ -372,7 +369,7 @@ dead_elem:
                nft_trans_gc_elem_add(gc, he);
        }
 
-       gc = nft_trans_gc_catchall(gc, gc_seq);
+       gc = nft_trans_gc_catchall_async(gc, gc_seq);
 
 try_later:
        /* catchall list iteration requires rcu read side lock. */
index 6af9c9ed4b5c3049353fd50b16080f34cd660a6f..c0dcc40de358fb2f364ed15f05a5b166279887aa 100644 (file)
@@ -1596,7 +1596,7 @@ static void pipapo_gc(const struct nft_set *_set, struct nft_pipapo_match *m)
 
                        gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
                        if (!gc)
-                               break;
+                               return;
 
                        nft_pipapo_gc_deactivate(net, set, e);
                        pipapo_drop(m, rulemap);
@@ -1610,7 +1610,7 @@ static void pipapo_gc(const struct nft_set *_set, struct nft_pipapo_match *m)
                }
        }
 
-       gc = nft_trans_gc_catchall(gc, 0);
+       gc = nft_trans_gc_catchall_sync(gc);
        if (gc) {
                nft_trans_gc_queue_sync_done(gc);
                priv->last_gc = jiffies;
index f250b5399344afac46bfca4014367bf57cf18ffe..487572dcd614436a22d755a286f1c341b9b3a850 100644 (file)
@@ -622,8 +622,7 @@ static void nft_rbtree_gc(struct work_struct *work)
        if (!gc)
                goto done;
 
-       write_lock_bh(&priv->lock);
-       write_seqcount_begin(&priv->count);
+       read_lock_bh(&priv->lock);
        for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) {
 
                /* Ruleset has been updated, try later. */
@@ -670,11 +669,10 @@ dead_elem:
                nft_trans_gc_elem_add(gc, rbe);
        }
 
-       gc = nft_trans_gc_catchall(gc, gc_seq);
+       gc = nft_trans_gc_catchall_async(gc, gc_seq);
 
 try_later:
-       write_seqcount_end(&priv->count);
-       write_unlock_bh(&priv->lock);
+       read_unlock_bh(&priv->lock);
 
        if (gc)
                nft_trans_gc_queue_async_done(gc);
index d36f3f6b43510dde1ef2e98515b41c6890d76ebf..b15cf316b23a221d47eaf0e7c38200840cc2442b 100644 (file)
@@ -86,11 +86,13 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
                break;
 
        case RDMA_CM_EVENT_ADDR_RESOLVED:
-               rdma_set_service_type(cm_id, conn->c_tos);
-               rdma_set_min_rnr_timer(cm_id, IB_RNR_TIMER_000_32);
-               /* XXX do we need to clean up if this fails? */
-               ret = rdma_resolve_route(cm_id,
-                                        RDS_RDMA_RESOLVE_TIMEOUT_MS);
+               if (conn) {
+                       rdma_set_service_type(cm_id, conn->c_tos);
+                       rdma_set_min_rnr_timer(cm_id, IB_RNR_TIMER_000_32);
+                       /* XXX do we need to clean up if this fails? */
+                       ret = rdma_resolve_route(cm_id,
+                                                RDS_RDMA_RESOLVE_TIMEOUT_MS);
+               }
                break;
 
        case RDMA_CM_EVENT_ROUTE_RESOLVED:
index bd01dd31e4bd736e86d20a849fe432b8c3a6aa6d..d520ee62c8ecd6cc6f172fbd953a5d102aab4e74 100644 (file)
@@ -1662,6 +1662,7 @@ void smcr_port_add(struct smc_ib_device *smcibdev, u8 ibport)
 {
        struct smc_link_group *lgr, *n;
 
+       spin_lock_bh(&smc_lgr_list.lock);
        list_for_each_entry_safe(lgr, n, &smc_lgr_list.list, list) {
                struct smc_link *link;
 
@@ -1680,6 +1681,7 @@ void smcr_port_add(struct smc_ib_device *smcibdev, u8 ibport)
                if (link)
                        smc_llc_add_link_local(link);
        }
+       spin_unlock_bh(&smc_lgr_list.lock);
 }
 
 /* link is down - switch connections to alternate link,
index b60fe1eb37ab66031474033988f7457129b3d290..aa8928975cc633cf169059713226d737e1634293 100644 (file)
@@ -243,8 +243,9 @@ while (0)
 #define SMC_STAT_SERV_SUCC_INC(net, _ini) \
 do { \
        typeof(_ini) i = (_ini); \
-       bool is_v2 = (i->smcd_version & SMC_V2); \
        bool is_smcd = (i->is_smcd); \
+       u8 version = is_smcd ? i->smcd_version : i->smcr_version; \
+       bool is_v2 = (version & SMC_V2); \
        typeof(net->smc.smc_stats) smc_stats = (net)->smc.smc_stats; \
        if (is_v2 && is_smcd) \
                this_cpu_inc(smc_stats->smc[SMC_TYPE_D].srv_v2_succ_cnt); \
index 8d75290f1a31d23d5f61439c18549ed76c36ced8..37b0b212b934757fcb59cfc9a8de32d006c2ee30 100644 (file)
@@ -2725,7 +2725,7 @@ out_unparsable:
 
 out_verifier:
        trace_rpc_bad_verifier(task);
-       goto out_err;
+       goto out_garbage;
 
 out_msg_denied:
        error = -EACCES;
@@ -2751,6 +2751,7 @@ out_msg_denied:
        case rpc_autherr_rejectedverf:
        case rpcsec_gsserr_credproblem:
        case rpcsec_gsserr_ctxproblem:
+               rpcauth_invalcred(task);
                if (!task->tk_cred_retry)
                        break;
                task->tk_cred_retry--;
@@ -2907,19 +2908,22 @@ static const struct rpc_call_ops rpc_cb_add_xprt_call_ops = {
  * @clnt: pointer to struct rpc_clnt
  * @xps: pointer to struct rpc_xprt_switch,
  * @xprt: pointer struct rpc_xprt
- * @dummy: unused
+ * @in_max_connect: pointer to the max_connect value for the passed in xprt transport
  */
 int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt,
                struct rpc_xprt_switch *xps, struct rpc_xprt *xprt,
-               void *dummy)
+               void *in_max_connect)
 {
        struct rpc_cb_add_xprt_calldata *data;
        struct rpc_task *task;
+       int max_connect = clnt->cl_max_connect;
 
-       if (xps->xps_nunique_destaddr_xprts + 1 > clnt->cl_max_connect) {
+       if (in_max_connect)
+               max_connect = *(int *)in_max_connect;
+       if (xps->xps_nunique_destaddr_xprts + 1 > max_connect) {
                rcu_read_lock();
                pr_warn("SUNRPC: reached max allowed number (%d) did not add "
-                       "transport to server: %s\n", clnt->cl_max_connect,
+                       "transport to server: %s\n", max_connect,
                        rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR));
                rcu_read_unlock();
                return -EINVAL;
index 1ed4a611631fe4e01d6646b6c2d7fc0d505611fc..d1fc295b83b59a03a472f8b9d3d740765bad7fbb 100644 (file)
@@ -817,7 +817,7 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, struct sock *sk,
        psock = sk_psock_get(sk);
        if (!psock || !policy) {
                err = tls_push_record(sk, flags, record_type);
-               if (err && sk->sk_err == EBADMSG) {
+               if (err && err != -EINPROGRESS && sk->sk_err == EBADMSG) {
                        *copied -= sk_msg_free(sk, msg);
                        tls_free_open_rec(sk);
                        err = -sk->sk_err;
@@ -846,7 +846,7 @@ more_data:
        switch (psock->eval) {
        case __SK_PASS:
                err = tls_push_record(sk, flags, record_type);
-               if (err && sk->sk_err == EBADMSG) {
+               if (err && err != -EINPROGRESS && sk->sk_err == EBADMSG) {
                        *copied -= sk_msg_free(sk, msg);
                        tls_free_open_rec(sk);
                        err = -sk->sk_err;
index c59cc57286ba4669bd113018a9133ee2642bf15c..346f5ec506823e05fc4f2864223b2df574b0c842 100644 (file)
@@ -113,7 +113,7 @@ quiet_cmd_sign :=
 endif
 
 # Create necessary directories
-$(shell mkdir -p $(sort $(dir $(install-y))))
+$(foreach dir, $(sort $(dir $(install-y))), $(shell mkdir -p $(dir)))
 
 $(dst)/%.ko: $(extmod_prefix)%.ko FORCE
        $(call cmd,install)
index c0c8a85d7c81b56d8f8c66b96021898e482f7043..a45154cefa487a81ef87ba12a2f79c42f070df00 100755 (executable)
@@ -102,7 +102,7 @@ gen_proto_order_variant()
        fi
 
        # Allow ACQUIRE/RELEASE/RELAXED ops to be defined in terms of FULL ops
-       if [ ! -z "${order}" ]; then
+       if [ ! -z "${order}" ] && ! meta_is_implicitly_relaxed "${meta}"; then
                printf "#elif defined(arch_${basename})\n"
                printf "\t${retstmt}arch_${basename}(${args});\n"
        fi
index 5179edd1b6271d676a43c2edff5e8ecc218ea6c6..c8047f4441e60ea944ae6fccedf0e4d0d7632dcd 100644 (file)
@@ -111,12 +111,11 @@ lx-symbols command."""
         return "{textaddr} {sections}".format(
             textaddr=textaddr, sections="".join(args))
 
-    def load_module_symbols(self, module, module_file=None):
+    def load_module_symbols(self, module):
         module_name = module['name'].string()
         module_addr = str(module['mem'][constants.LX_MOD_TEXT]['base']).split()[0]
 
-        if not module_file:
-            module_file = self._get_module_file(module_name)
+        module_file = self._get_module_file(module_name)
         if not module_file and not self.module_files_updated:
             self._update_module_files()
             module_file = self._get_module_file(module_name)
@@ -139,19 +138,6 @@ lx-symbols command."""
         else:
             gdb.write("no module object found for '{0}'\n".format(module_name))
 
-    def load_ko_symbols(self, mod_path):
-        self.loaded_modules = []
-        module_list = modules.module_list()
-
-        for module in module_list:
-            module_name = module['name'].string()
-            module_pattern = ".*/{0}\.ko(?:.debug)?$".format(
-                module_name.replace("_", r"[_\-]"))
-            if re.match(module_pattern, mod_path) and os.path.exists(mod_path):
-                self.load_module_symbols(module, mod_path)
-                return
-        raise gdb.GdbError("%s is not a valid .ko\n" % mod_path)
-
     def load_all_symbols(self):
         gdb.write("loading vmlinux\n")
 
@@ -190,11 +176,6 @@ lx-symbols command."""
         self.module_files = []
         self.module_files_updated = False
 
-        argv = gdb.string_to_argv(arg)
-        if len(argv) == 1:
-            self.load_ko_symbols(argv[0])
-            return
-
         self.load_all_symbols()
 
         if hasattr(gdb, 'Breakpoint'):
index 34a5386d444a6f2943ed52f88088a464185d2c46..de499dce52652798e8ed731a4544aecc07f15be5 100644 (file)
@@ -1228,6 +1228,15 @@ static void check_export_symbol(struct module *mod, struct elf_info *elf,
         */
        s->is_func = (ELF_ST_TYPE(sym->st_info) == STT_FUNC);
 
+       /*
+        * For parisc64, symbols prefixed $$ from the library have the symbol type
+        * STT_LOPROC. They should be handled as functions too.
+        */
+       if (elf->hdr->e_ident[EI_CLASS] == ELFCLASS64 &&
+           elf->hdr->e_machine == EM_PARISC &&
+           ELF_ST_TYPE(sym->st_info) == STT_LOPROC)
+               s->is_func = true;
+
        if (match(secname, PATTERNS(INIT_SECTIONS)))
                warn("%s: %s: EXPORT_SYMBOL used for init symbol. Remove __init or EXPORT_SYMBOL.\n",
                     mod->name, name);
index af7fe9f5b1e4d3d79569d47f392a12cbea65accd..8a7051fad0878990cd4569a326fc7137a7db088d 100755 (executable)
@@ -20,7 +20,7 @@ mkdir -p "${destdir}"
        find "arch/${SRCARCH}" -maxdepth 1 -name 'Makefile*'
        find include scripts -type f -o -type l
        find "arch/${SRCARCH}" -name Kbuild.platforms -o -name Platform
-       find "$(find "arch/${SRCARCH}" -name include -o -name scripts -type d)" -type f
+       find "arch/${SRCARCH}" -name include -o -name scripts -type d
 ) | tar -c -f - -C "${srctree}" -T - | tar -xf - -C "${destdir}"
 
 {
index 10350534de6d65b3a4103ae9babe42fac3682261..2aa0e219d72177799b915322d73e0af1698901f6 100644 (file)
@@ -2775,14 +2775,20 @@ static int selinux_umount(struct vfsmount *mnt, int flags)
 static int selinux_fs_context_submount(struct fs_context *fc,
                                   struct super_block *reference)
 {
-       const struct superblock_security_struct *sbsec;
+       const struct superblock_security_struct *sbsec = selinux_superblock(reference);
        struct selinux_mnt_opts *opts;
 
+       /*
+        * Ensure that fc->security remains NULL when no options are set
+        * as expected by selinux_set_mnt_opts().
+        */
+       if (!(sbsec->flags & (FSCONTEXT_MNT|CONTEXT_MNT|DEFCONTEXT_MNT)))
+               return 0;
+
        opts = kzalloc(sizeof(*opts), GFP_KERNEL);
        if (!opts)
                return -ENOMEM;
 
-       sbsec = selinux_superblock(reference);
        if (sbsec->flags & FSCONTEXT_MNT)
                opts->fscontext_sid = sbsec->sid;
        if (sbsec->flags & CONTEXT_MNT)
index d61bde1225f23a362aa4c2edd64ec9ec32fc1987..22c0d217b8608f04b4c9c1803379b9546f12ed14 100644 (file)
@@ -278,9 +278,6 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
                         size_t extra_size)
 {
        int err;
-#ifdef CONFIG_SND_DEBUG
-       char name[8];
-#endif
 
        if (extra_size > 0)
                card->private_data = (char *)card + sizeof(struct snd_card);
@@ -364,8 +361,8 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
        }
 
 #ifdef CONFIG_SND_DEBUG
-       sprintf(name, "card%d", idx);
-       card->debugfs_root = debugfs_create_dir(name, sound_debugfs_root);
+       card->debugfs_root = debugfs_create_dir(dev_name(&card->card_dev),
+                                               sound_debugfs_root);
 #endif
        return 0;
 
index ba06484ac4aa9b6f7f05be7c63187cb22341df7b..1431cb997808d071d44efadba2b8a1d49117ee25 100644 (file)
@@ -1770,7 +1770,7 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
        if (IS_ENABLED(CONFIG_SND_UMP))
                snd_iprintf(buffer, "Type: %s\n",
                            rawmidi_is_ump(rmidi) ? "UMP" : "Legacy");
-       if (rmidi->ops->proc_read)
+       if (rmidi->ops && rmidi->ops->proc_read)
                rmidi->ops->proc_read(entry, buffer);
        mutex_lock(&rmidi->open_mutex);
        if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT) {
index 44302d98950e89aca5de30ca166b5e3ba6de9c7c..18320a248aa7daa080df9499668c400f4da22066 100644 (file)
@@ -349,9 +349,9 @@ snd_seq_midisynth_probe(struct device *_dev)
                if (! port->name[0]) {
                        if (info->name[0]) {
                                if (ports > 1)
-                                       snprintf(port->name, sizeof(port->name), "%s-%u", info->name, p);
+                                       scnprintf(port->name, sizeof(port->name), "%s-%u", info->name, p);
                                else
-                                       snprintf(port->name, sizeof(port->name), "%s", info->name);
+                                       scnprintf(port->name, sizeof(port->name), "%s", info->name);
                        } else {
                                /* last resort */
                                if (ports > 1)
index f26a1812dfa73e564aaf77f8197045c8e9a3a933..2db371d79930d0f2af7630f50901a3d69006e538 100644 (file)
@@ -207,7 +207,7 @@ static void fill_port_info(struct snd_seq_port_info *port,
                SNDRV_SEQ_PORT_TYPE_PORT;
        port->midi_channels = 16;
        if (*group->name)
-               snprintf(port->name, sizeof(port->name), "Group %d (%s)",
+               snprintf(port->name, sizeof(port->name), "Group %d (%.53s)",
                         group->group + 1, group->name);
        else
                sprintf(port->name, "Group %d", group->group + 1);
@@ -416,6 +416,25 @@ static void setup_client_midi_version(struct seq_ump_client *client)
        snd_seq_kernel_client_put(cptr);
 }
 
+/* set up client's group_filter bitmap */
+static void setup_client_group_filter(struct seq_ump_client *client)
+{
+       struct snd_seq_client *cptr;
+       unsigned int filter;
+       int p;
+
+       cptr = snd_seq_kernel_client_get(client->seq_client);
+       if (!cptr)
+               return;
+       filter = ~(1U << 0); /* always allow groupless messages */
+       for (p = 0; p < SNDRV_UMP_MAX_GROUPS; p++) {
+               if (client->groups[p].active)
+                       filter &= ~(1U << (p + 1));
+       }
+       cptr->group_filter = filter;
+       snd_seq_kernel_client_put(cptr);
+}
+
 /* UMP group change notification */
 static void handle_group_notify(struct work_struct *work)
 {
@@ -424,6 +443,7 @@ static void handle_group_notify(struct work_struct *work)
 
        update_group_attrs(client);
        update_port_infos(client);
+       setup_client_group_filter(client);
 }
 
 /* UMP FB change notification */
@@ -492,6 +512,8 @@ static int snd_seq_ump_probe(struct device *_dev)
                        goto error;
        }
 
+       setup_client_group_filter(client);
+
        err = create_ump_endpoint_port(client);
        if (err < 0)
                goto error;
index 7cc84e137999cd8e5a38ac6913e4a9cbc58fc4d0..b141024830ecc831430c697858ce409a56c711af 100644 (file)
@@ -1197,6 +1197,8 @@ int snd_seq_deliver_to_ump(struct snd_seq_client *source,
                           struct snd_seq_event *event,
                           int atomic, int hop)
 {
+       if (dest->group_filter & (1U << dest_port->ump_group))
+               return 0; /* group filtered - skip the event */
        if (event->type == SNDRV_SEQ_EVENT_SYSEX)
                return cvt_sysex_to_ump(dest, dest_port, event, atomic, hop);
        else if (snd_seq_client_is_midi2(dest))
index 6f597d03e7c157ae45476cfd888e64720d1604b0..b1425bf98c3befd7237c6b19920c86667dabe16e 100644 (file)
@@ -84,9 +84,9 @@ static void set_midi_substream_names(struct snd_bebob *bebob,
        struct snd_rawmidi_substream *subs;
 
        list_for_each_entry(subs, &str->substreams, list) {
-               snprintf(subs->name, sizeof(subs->name),
-                        "%s MIDI %d",
-                        bebob->card->shortname, subs->number + 1);
+               scnprintf(subs->name, sizeof(subs->name),
+                         "%s MIDI %d",
+                         bebob->card->shortname, subs->number + 1);
        }
 }
 
index 4c2998034313587ac8a53f18ad708db6fb32e4a7..78988e44b8bcd23329dfd929e144c13163e8602b 100644 (file)
@@ -88,8 +88,8 @@ static void set_midi_substream_names(struct snd_dice *dice,
        struct snd_rawmidi_substream *subs;
 
        list_for_each_entry(subs, &str->substreams, list) {
-               snprintf(subs->name, sizeof(subs->name),
-                        "%s MIDI %d", dice->card->shortname, subs->number + 1);
+               scnprintf(subs->name, sizeof(subs->name),
+                         "%s MIDI %d", dice->card->shortname, subs->number + 1);
        }
 }
 
index 68eb8c39afa6c58ea7994172ea1773b5ac654aed..8f4bace16050a16248c9c117af9cc0888bbf0463 100644 (file)
@@ -100,14 +100,14 @@ static void set_substream_names(struct snd_dg00x *dg00x,
 
                list_for_each_entry(subs, &str->substreams, list) {
                        if (!is_console) {
-                               snprintf(subs->name, sizeof(subs->name),
-                                        "%s MIDI %d",
-                                        dg00x->card->shortname,
-                                        subs->number + 1);
+                               scnprintf(subs->name, sizeof(subs->name),
+                                         "%s MIDI %d",
+                                         dg00x->card->shortname,
+                                         subs->number + 1);
                        } else {
-                               snprintf(subs->name, sizeof(subs->name),
-                                        "%s control",
-                                        dg00x->card->shortname);
+                               scnprintf(subs->name, sizeof(subs->name),
+                                         "%s control",
+                                         dg00x->card->shortname);
                        }
                }
        }
index 25821d186b878f67a389c474ff3d0caf855be3da..da3054fdcc7d66050f51abc09cb2dd6ac309597e 100644 (file)
@@ -79,8 +79,8 @@ static void set_midi_substream_names(struct snd_rawmidi_str *stream,
        struct snd_rawmidi_substream *substream;
 
        list_for_each_entry(substream, &stream->substreams, list) {
-               snprintf(substream->name, sizeof(substream->name),
-                        "%s MIDI %d", name, substream->number + 1);
+               scnprintf(substream->name, sizeof(substream->name),
+                         "%s MIDI %d", name, substream->number + 1);
        }
 }
 
index dd4298876ac087954ae37e3f20ceea93b3362ed6..e3ed4e094ccd0e8311a053878cb9d5e7c429a46b 100644 (file)
@@ -93,11 +93,11 @@ get_hardware_info(struct snd_efw *efw)
        strcpy(efw->card->driver, "Fireworks");
        strcpy(efw->card->shortname, hwinfo->model_name);
        strcpy(efw->card->mixername, hwinfo->model_name);
-       snprintf(efw->card->longname, sizeof(efw->card->longname),
-                "%s %s v%s, GUID %08x%08x at %s, S%d",
-                hwinfo->vendor_name, hwinfo->model_name, version,
-                hwinfo->guid_hi, hwinfo->guid_lo,
-                dev_name(&efw->unit->device), 100 << fw_dev->max_speed);
+       scnprintf(efw->card->longname, sizeof(efw->card->longname),
+                 "%s %s v%s, GUID %08x%08x at %s, S%d",
+                 hwinfo->vendor_name, hwinfo->model_name, version,
+                 hwinfo->guid_hi, hwinfo->guid_lo,
+                 dev_name(&efw->unit->device), 100 << fw_dev->max_speed);
 
        if (hwinfo->flags & BIT(FLAG_RESP_ADDR_CHANGABLE))
                efw->resp_addr_changable = true;
index 84621e3568482431d4334a5d4afb773dfb4a63a7..350bf4d299c2009571427b75b0378314c2965f05 100644 (file)
@@ -84,8 +84,8 @@ static void set_midi_substream_names(struct snd_efw *efw,
        struct snd_rawmidi_substream *subs;
 
        list_for_each_entry(subs, &str->substreams, list) {
-               snprintf(subs->name, sizeof(subs->name),
-                        "%s MIDI %d", efw->card->shortname, subs->number + 1);
+               scnprintf(subs->name, sizeof(subs->name),
+                         "%s MIDI %d", efw->card->shortname, subs->number + 1);
        }
 }
 
index 2365f7dfde2664dfa3990e2e8ab848b2de5ada4d..eebc7e790ee2ab682ea024d6b82723252f995bd4 100644 (file)
@@ -88,8 +88,8 @@ static void set_midi_substream_names(struct snd_motu *motu,
        struct snd_rawmidi_substream *subs;
 
        list_for_each_entry(subs, &str->substreams, list) {
-               snprintf(subs->name, sizeof(subs->name),
-                        "%s MIDI %d", motu->card->shortname, subs->number + 1);
+               scnprintf(subs->name, sizeof(subs->name),
+                         "%s MIDI %d", motu->card->shortname, subs->number + 1);
        }
 }
 
index 775cba3f1f028a03853394443ddc92e9aecad912..c215fa6f7a03713e946b276016fc80f5585d4d9e 100644 (file)
@@ -129,9 +129,9 @@ static void set_midi_substream_names(struct snd_oxfw *oxfw,
        struct snd_rawmidi_substream *subs;
 
        list_for_each_entry(subs, &str->substreams, list) {
-               snprintf(subs->name, sizeof(subs->name),
-                        "%s MIDI %d",
-                        oxfw->card->shortname, subs->number + 1);
+               scnprintf(subs->name, sizeof(subs->name),
+                         "%s MIDI %d",
+                         oxfw->card->shortname, subs->number + 1);
        }
 }
 
index 63d40f1a914f8c710bcdc2e57cf3794102d475b7..241a697ce26b2585f7271ef6e9ae0cbcadce879b 100644 (file)
@@ -108,11 +108,11 @@ static int name_card(struct snd_oxfw *oxfw, const struct ieee1394_device_id *ent
        strcpy(oxfw->card->mixername, m);
        strcpy(oxfw->card->shortname, m);
 
-       snprintf(oxfw->card->longname, sizeof(oxfw->card->longname),
-                "%s %s (OXFW%x %04x), GUID %08x%08x at %s, S%d",
-                v, m, firmware >> 20, firmware & 0xffff,
-                fw_dev->config_rom[3], fw_dev->config_rom[4],
-                dev_name(&oxfw->unit->device), 100 << fw_dev->max_speed);
+       scnprintf(oxfw->card->longname, sizeof(oxfw->card->longname),
+                 "%s %s (OXFW%x %04x), GUID %08x%08x at %s, S%d",
+                 v, m, firmware >> 20, firmware & 0xffff,
+                 fw_dev->config_rom[3], fw_dev->config_rom[4],
+                 dev_name(&oxfw->unit->device), 100 << fw_dev->max_speed);
 end:
        return err;
 }
index 02eed2dce435f24e41f2f5a5b06104d52c2f10e0..c57fac4f196819462aac2d0ebc11f03c16ce36fc 100644 (file)
@@ -108,9 +108,9 @@ int snd_tscm_create_midi_devices(struct snd_tscm *tscm)
                /* TODO: support virtual MIDI ports. */
                if (subs->number < tscm->spec->midi_capture_ports) {
                        /* Hardware MIDI ports. */
-                       snprintf(subs->name, sizeof(subs->name),
-                                "%s MIDI %d",
-                                tscm->card->shortname, subs->number + 1);
+                       scnprintf(subs->name, sizeof(subs->name),
+                                 "%s MIDI %d",
+                                 tscm->card->shortname, subs->number + 1);
                }
        }
 
@@ -123,9 +123,9 @@ int snd_tscm_create_midi_devices(struct snd_tscm *tscm)
        list_for_each_entry(subs, &stream->substreams, list) {
                if (subs->number < tscm->spec->midi_playback_ports) {
                        /* Hardware MIDI ports only. */
-                       snprintf(subs->name, sizeof(subs->name),
-                                "%s MIDI %d",
-                                tscm->card->shortname, subs->number + 1);
+                       scnprintf(subs->name, sizeof(subs->name),
+                                 "%s MIDI %d",
+                                 tscm->card->shortname, subs->number + 1);
                }
        }
 
index 5cb92f7ccbcac991f95aa1fd2ecea60486fe9248..b57d72ea4503fa7504757eb6542b51e5b2e7b5e9 100644 (file)
@@ -23,7 +23,7 @@ static int ctrl_link_mask;
 module_param_named(sdw_link_mask, ctrl_link_mask, int, 0444);
 MODULE_PARM_DESC(sdw_link_mask, "Intel link mask (one bit per link)");
 
-static bool is_link_enabled(struct fwnode_handle *fw_node, int i)
+static bool is_link_enabled(struct fwnode_handle *fw_node, u8 idx)
 {
        struct fwnode_handle *link;
        char name[32];
@@ -31,7 +31,7 @@ static bool is_link_enabled(struct fwnode_handle *fw_node, int i)
 
        /* Find master handle */
        snprintf(name, sizeof(name),
-                "mipi-sdw-link-%d-subproperties", i);
+                "mipi-sdw-link-%hhu-subproperties", idx);
 
        link = fwnode_get_named_child_node(fw_node, name);
        if (!link)
@@ -51,8 +51,8 @@ static int
 sdw_intel_scan_controller(struct sdw_intel_acpi_info *info)
 {
        struct acpi_device *adev = acpi_fetch_acpi_dev(info->handle);
-       int ret, i;
-       u8 count;
+       u8 count, i;
+       int ret;
 
        if (!adev)
                return -EINVAL;
index c471ac2aa450a1a4ee65d60ca5fad3e47d3d053f..401d8df28d8767a8b1159494d30ab497e6958ffc 100644 (file)
@@ -96,13 +96,13 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n)
        strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
 
        if (!thinkpad[n])
-               snprintf(card->longname, sizeof(card->longname),
-                        "%s at 0x%lx, irq %d, dma %d",
-                        chip->pcm->name, chip->port, irq[n], dma1[n]);
+               scnprintf(card->longname, sizeof(card->longname),
+                         "%s at 0x%lx, irq %d, dma %d",
+                         chip->pcm->name, chip->port, irq[n], dma1[n]);
        else
-               snprintf(card->longname, sizeof(card->longname),
-                        "%s at 0x%lx, irq %d, dma %d [Thinkpad]",
-                        chip->pcm->name, chip->port, irq[n], dma1[n]);
+               scnprintf(card->longname, sizeof(card->longname),
+                         "%s at 0x%lx, irq %d, dma %d [Thinkpad]",
+                         chip->pcm->name, chip->port, irq[n], dma1[n]);
 
        error = snd_card_register(card);
        if (error < 0)
index 1e89233853662046f4161a767877ad87f67a8967..c87be4be6df1d4afeb9c62936a57de4a02297bed 100644 (file)
@@ -98,13 +98,13 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n)
        strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
 
        if (dma2[n] < 0)
-               snprintf(card->longname, sizeof(card->longname),
-                        "%s at 0x%lx, irq %d, dma %d",
-                        chip->pcm->name, chip->port, irq[n], dma1[n]);
+               scnprintf(card->longname, sizeof(card->longname),
+                         "%s at 0x%lx, irq %d, dma %d",
+                         chip->pcm->name, chip->port, irq[n], dma1[n]);
        else
-               snprintf(card->longname, sizeof(card->longname),
-                        "%s at 0x%lx, irq %d, dma %d&%d",
-                        chip->pcm->name, chip->port, irq[n], dma1[n], dma2[n]);
+               scnprintf(card->longname, sizeof(card->longname),
+                         "%s at 0x%lx, irq %d, dma %d&%d",
+                         chip->pcm->name, chip->port, irq[n], dma1[n], dma2[n]);
 
        error = snd_wss_mixer(chip);
        if (error < 0)
index 10112e1bb25dc2373c77ae3ef0d120d328a91030..7226cbf2d7de4c5736cbd31858c727bd7b4e2917 100644 (file)
@@ -367,14 +367,14 @@ static int snd_cs423x_probe(struct snd_card *card, int dev)
        strscpy(card->driver, chip->pcm->name, sizeof(card->driver));
        strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
        if (dma2[dev] < 0)
-               snprintf(card->longname, sizeof(card->longname),
-                        "%s at 0x%lx, irq %i, dma %i",
-                        chip->pcm->name, chip->port, irq[dev], dma1[dev]);
+               scnprintf(card->longname, sizeof(card->longname),
+                         "%s at 0x%lx, irq %i, dma %i",
+                         chip->pcm->name, chip->port, irq[dev], dma1[dev]);
        else
-               snprintf(card->longname, sizeof(card->longname),
-                        "%s at 0x%lx, irq %i, dma %i&%d",
-                        chip->pcm->name, chip->port, irq[dev], dma1[dev],
-                        dma2[dev]);
+               scnprintf(card->longname, sizeof(card->longname),
+                         "%s at 0x%lx, irq %i, dma %i&%d",
+                         chip->pcm->name, chip->port, irq[dev], dma1[dev],
+                         dma2[dev]);
 
        err = snd_wss_timer(chip, 0);
        if (err < 0)
index f935b56eeec7bfc1baceeb4285c49c3dadeb1c35..97728bf45474238d500aaead219a8d5e3396ae00 100644 (file)
@@ -130,9 +130,9 @@ static int snd_es1688_probe(struct snd_card *card, unsigned int n)
 
        strscpy(card->driver, "ES1688", sizeof(card->driver));
        strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
-       snprintf(card->longname, sizeof(card->longname),
-               "%s at 0x%lx, irq %i, dma %i", chip->pcm->name, chip->port,
-                chip->irq, chip->dma8);
+       scnprintf(card->longname, sizeof(card->longname),
+                 "%s at 0x%lx, irq %i, dma %i", chip->pcm->name, chip->port,
+                 chip->irq, chip->dma8);
 
        if (fm_port[n] == SNDRV_AUTO_PORT)
                fm_port[n] = port[n];   /* share the same port */
index 59242baed576410d5a2d82d854e79901f1e95842..59792f2fada1d578154c25e11d61ef8153b5689e 100644 (file)
@@ -1344,10 +1344,10 @@ static int snd_miro_probe(struct snd_card *card)
        }
 
        strcpy(card->driver, "miro");
-       snprintf(card->longname, sizeof(card->longname),
-                "%s: OPTi%s, %s at 0x%lx, irq %d, dma %d&%d",
-                card->shortname, miro->name, codec->pcm->name,
-                miro->wss_base + 4, miro->irq, miro->dma1, miro->dma2);
+       scnprintf(card->longname, sizeof(card->longname),
+                 "%s: OPTi%s, %s at 0x%lx, irq %d, dma %d&%d",
+                 card->shortname, miro->name, codec->pcm->name,
+                 miro->wss_base + 4, miro->irq, miro->dma1, miro->dma2);
 
        if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT)
                rmidi = NULL;
index 4beeb32fe2a7a9d0bbfb999bbbd6c9020bf3a58a..c33f67dd51331acf457d74b02926dc8392e8a673 100644 (file)
@@ -859,15 +859,15 @@ static int snd_opti9xx_probe(struct snd_card *card)
        strcpy(card->driver, chip->name);
        sprintf(card->shortname, "OPTi %s", card->driver);
 #if defined(CS4231) || defined(OPTi93X)
-       snprintf(card->longname, sizeof(card->longname),
-                "%s, %s at 0x%lx, irq %d, dma %d&%d",
-                card->shortname, codec->pcm->name,
-                chip->wss_base + 4, irq, dma1, xdma2);
+       scnprintf(card->longname, sizeof(card->longname),
+                 "%s, %s at 0x%lx, irq %d, dma %d&%d",
+                 card->shortname, codec->pcm->name,
+                 chip->wss_base + 4, irq, dma1, xdma2);
 #else
-       snprintf(card->longname, sizeof(card->longname),
-                "%s, %s at 0x%lx, irq %d, dma %d",
-                card->shortname, codec->pcm->name, chip->wss_base + 4, irq,
-                dma1);
+       scnprintf(card->longname, sizeof(card->longname),
+                 "%s, %s at 0x%lx, irq %d, dma %d",
+                 card->shortname, codec->pcm->name, chip->wss_base + 4, irq,
+                 dma1);
 #endif /* CS4231 || OPTi93X */
 
        if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT)
index 0bc0025f7c199a6c678e2bf8c949b33fe882ff28..cc56fafd27b1253e301d58f493b89d17fbdaba08 100644 (file)
@@ -557,7 +557,7 @@ static int sscape_upload_microcode(struct snd_card *card, int version)
        char name[14];
        int err;
 
-       snprintf(name, sizeof(name), "sndscape.co%d", version);
+       scnprintf(name, sizeof(name), "sndscape.co%d", version);
 
        err = request_firmware(&init_fw, name, card->dev);
        if (err < 0) {
index 1415baac9c361349932e2c67d6a97e9a18513527..08e34b184780187f66922448c40761e6281d84a2 100644 (file)
@@ -3102,11 +3102,13 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
        }
        sprintf(card->shortname, "C-Media CMI%d", val);
        if (cm->chip_version < 68)
-               sprintf(modelstr, " (model %d)", cm->chip_version);
+               scnprintf(modelstr, sizeof(modelstr),
+                         " (model %d)", cm->chip_version);
        else
                modelstr[0] = '\0';
-       sprintf(card->longname, "%s%s at %#lx, irq %i",
-               card->shortname, modelstr, cm->iobase, cm->irq);
+       scnprintf(card->longname, sizeof(card->longname),
+                 "%s%s at %#lx, irq %i",
+                 card->shortname, modelstr, cm->iobase, cm->irq);
 
        if (cm->chip_version >= 39) {
                val = snd_cmipci_read_b(cm, CM_REG_MPU_PCI + 1);
index 76b9c685560bf078ec856843f0db1f42969c7508..7adc1d373d65c377cf2db29f4a6bb63b57db0bb4 100644 (file)
@@ -105,7 +105,7 @@ static void cs35l56_hda_playback_hook(struct device *dev, int action)
        }
 }
 
-static int __maybe_unused cs35l56_hda_runtime_suspend(struct device *dev)
+static int cs35l56_hda_runtime_suspend(struct device *dev)
 {
        struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);
 
@@ -115,7 +115,7 @@ static int __maybe_unused cs35l56_hda_runtime_suspend(struct device *dev)
        return cs35l56_runtime_suspend_common(&cs35l56->base);
 }
 
-static int __maybe_unused cs35l56_hda_runtime_resume(struct device *dev)
+static int cs35l56_hda_runtime_resume(struct device *dev)
 {
        struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);
        int ret;
@@ -218,7 +218,7 @@ static int cs35l56_hda_posture_get(struct snd_kcontrol *kcontrol,
 
        ucontrol->value.integer.value[0] = pos;
 
-       return ret;
+       return 0;
 }
 
 static int cs35l56_hda_posture_put(struct snd_kcontrol *kcontrol,
@@ -865,15 +865,13 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int id)
        sub = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev));
 
        if (IS_ERR(sub)) {
-               /* If no ACPI SUB, return 0 and fallback to legacy firmware path, otherwise fail */
-               if (PTR_ERR(sub) == -ENODATA)
-                       return 0;
-               else
-                       return PTR_ERR(sub);
+               dev_info(cs35l56->base.dev,
+                        "Read ACPI _SUB failed(%ld): fallback to generic firmware\n",
+                        PTR_ERR(sub));
+       } else {
+               cs35l56->system_name = sub;
        }
 
-       cs35l56->system_name = sub;
-
        cs35l56->base.reset_gpio = devm_gpiod_get_index_optional(cs35l56->base.dev,
                                                                 "reset",
                                                                 cs35l56->index,
@@ -1003,6 +1001,7 @@ void cs35l56_hda_remove(struct device *dev)
 {
        struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);
 
+       pm_runtime_dont_use_autosuspend(cs35l56->base.dev);
        pm_runtime_get_sync(cs35l56->base.dev);
        pm_runtime_disable(cs35l56->base.dev);
 
@@ -1016,7 +1015,7 @@ void cs35l56_hda_remove(struct device *dev)
 EXPORT_SYMBOL_NS_GPL(cs35l56_hda_remove, SND_HDA_SCODEC_CS35L56);
 
 const struct dev_pm_ops cs35l56_hda_pm_ops = {
-       SET_RUNTIME_PM_OPS(cs35l56_hda_runtime_suspend, cs35l56_hda_runtime_resume, NULL)
+       RUNTIME_PM_OPS(cs35l56_hda_runtime_suspend, cs35l56_hda_runtime_resume, NULL)
        SYSTEM_SLEEP_PM_OPS(cs35l56_hda_system_suspend, cs35l56_hda_system_resume)
        LATE_SYSTEM_SLEEP_PM_OPS(cs35l56_hda_system_suspend_late,
                                 cs35l56_hda_system_resume_early)
index 83e4acdd89aceddb9d8671728b752d3611f2f2d8..757a4d193e0fb5919778847693a3353f2825265b 100644 (file)
@@ -21,7 +21,6 @@ static int cs35l56_hda_i2c_probe(struct i2c_client *clt)
                return -ENOMEM;
 
        cs35l56->base.dev = &clt->dev;
-       cs35l56->base.can_hibernate = true;
        cs35l56->base.regmap = devm_regmap_init_i2c(clt, &cs35l56_regmap_i2c);
        if (IS_ERR(cs35l56->base.regmap)) {
                ret = PTR_ERR(cs35l56->base.regmap);
index dbf7aa88e0e31a48a751e91761cfa644f98ab1c1..bf685d01259d30070aaf3ac7f3ed3204bc30c5bd 100644 (file)
@@ -998,7 +998,11 @@ static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
                                const char *sfx, int cidx, unsigned long val)
 {
        char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
-       snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
+       int len;
+
+       len = snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
+       if (snd_BUG_ON(len >= sizeof(name)))
+               return -EINVAL;
        if (!add_control(spec, type, name, cidx, val))
                return -ENOMEM;
        return 0;
index 765d95e7986171d2d2d3fed9ef2509db975f7074..ca765ac4765f4a27b77f81f466b647a9699f068d 100644 (file)
@@ -2211,6 +2211,7 @@ static const struct snd_pci_quirk power_save_denylist[] = {
        SND_PCI_QUIRK(0x8086, 0x2068, "Intel NUC7i3BNB", 0),
        /* https://bugzilla.kernel.org/show_bug.cgi?id=198611 */
        SND_PCI_QUIRK(0x17aa, 0x2227, "Lenovo X1 Carbon 3rd Gen", 0),
+       SND_PCI_QUIRK(0x17aa, 0x316e, "Lenovo ThinkCentre M70q", 0),
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1689623 */
        SND_PCI_QUIRK(0x17aa, 0x367b, "Lenovo IdeaCentre B550", 0),
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1572975 */
index b7e78bfcffd832a33df08cbc5d24b21b353c52d2..751783f3a15c2e5f7a19daf0d71fff3b81db19b0 100644 (file)
@@ -7073,8 +7073,10 @@ static void alc287_fixup_bind_dacs(struct hda_codec *codec,
        snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
        spec->gen.preferred_dacs = preferred_pairs;
        spec->gen.auto_mute_via_amp = 1;
-       snd_hda_codec_write_cache(codec, 0x14, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-                           0x0); /* Make sure 0x14 was disable */
+       if (spec->gen.autocfg.speaker_pins[0] != 0x14) {
+               snd_hda_codec_write_cache(codec, 0x14, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+                                       0x0); /* Make sure 0x14 was disable */
+       }
 }
 
 
@@ -9812,7 +9814,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1d1f, "ASUS ROG Strix G17 2023 (G713PV)", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401),
        SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
-       SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402", ALC245_FIXUP_CS35L41_SPI_2),
+       SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402ZA", ALC245_FIXUP_CS35L41_SPI_2),
+       SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS UX3402VA", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
        SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS),
@@ -10574,6 +10577,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x17, 0x90170110},
                {0x19, 0x03a11030},
                {0x21, 0x03211020}),
+       SND_HDA_PIN_QUIRK(0x10ec0287, 0x17aa, "Lenovo", ALC287_FIXUP_THINKPAD_I2S_SPK,
+               {0x17, 0x90170110}, /* 0x231f with RTK I2S AMP */
+               {0x19, 0x04a11040},
+               {0x21, 0x04211020}),
        SND_HDA_PIN_QUIRK(0x10ec0286, 0x1025, "Acer", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE,
                {0x12, 0x90a60130},
                {0x17, 0x90170110},
index b37c877c2c16057505fae4b206d74f96657c66f3..9dee0345f22cf1e550d38f1c3b3c7918e2f116c5 100644 (file)
@@ -2105,15 +2105,15 @@ __snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
        strcpy(card->driver, "RIPTIDE");
        strcpy(card->shortname, "Riptide");
 #ifdef SUPPORT_JOYSTICK
-       snprintf(card->longname, sizeof(card->longname),
-                "%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x gameport 0x%x",
-                card->shortname, chip->port, chip->irq, chip->mpuaddr,
-                chip->opladdr, chip->gameaddr);
+       scnprintf(card->longname, sizeof(card->longname),
+                 "%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x gameport 0x%x",
+                 card->shortname, chip->port, chip->irq, chip->mpuaddr,
+                 chip->opladdr, chip->gameaddr);
 #else
-       snprintf(card->longname, sizeof(card->longname),
-                "%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x",
-                card->shortname, chip->port, chip->irq, chip->mpuaddr,
-                chip->opladdr);
+       scnprintf(card->longname, sizeof(card->longname),
+                 "%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x",
+                 card->shortname, chip->port, chip->irq, chip->mpuaddr,
+                 chip->opladdr);
 #endif
        snd_riptide_proc_init(chip);
        err = snd_card_register(card);
index 3ec15b46fa35696f007ce86b4cec4cc35128937a..94e9eb8e73f2afbc7471bb81bfca59f20f23fdbd 100644 (file)
@@ -213,6 +213,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "21J6"),
                }
        },
+       {
+               .driver_data = &acp6x_card,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "82QF"),
+               }
+       },
        {
                .driver_data = &acp6x_card,
                .matches = {
@@ -220,6 +227,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "82TL"),
                }
        },
+       {
+               .driver_data = &acp6x_card,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "82UG"),
+               }
+       },
        {
                .driver_data = &acp6x_card,
                .matches = {
@@ -262,6 +276,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "M6500RC"),
                }
        },
+       {
+               .driver_data = &acp6x_card,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 B7ED"),
+               }
+       },
        {
                .driver_data = &acp6x_card,
                .matches = {
index 8ee1baa0326911d2ae39a5fa047e73a5e7aa7212..87dd0ccade4ce754b9962a4f931e2a80c2dc0ee8 100644 (file)
@@ -452,11 +452,13 @@ static int aw_dev_parse_reg_bin_with_hdr(struct aw_device *aw_dev,
        if ((aw_bin->all_bin_parse_num != 1) ||
                (aw_bin->header_info[0].bin_data_type != DATA_TYPE_REGISTER)) {
                dev_err(aw_dev->dev, "bin num or type error");
+               ret = -EINVAL;
                goto parse_bin_failed;
        }
 
        if (aw_bin->header_info[0].valid_data_len % 4) {
                dev_err(aw_dev->dev, "bin data len get error!");
+               ret = -EINVAL;
                goto parse_bin_failed;
        }
 
index 9f4f2f4f23f5668c846f2a051eee64c533deb38f..d10e0e2380e852a5ba3b59f749fa685d923634c0 100644 (file)
@@ -27,7 +27,6 @@ static int cs35l56_i2c_probe(struct i2c_client *client)
                return -ENOMEM;
 
        cs35l56->base.dev = dev;
-       cs35l56->base.can_hibernate = true;
 
        i2c_set_clientdata(client, cs35l56);
        cs35l56->base.regmap = devm_regmap_init_i2c(client, regmap_config);
index 600b79c62ec48a5dec9d843cb036477c7867f20a..f2e7c6d0be46c8b57e3701505196e7862d8f05a8 100644 (file)
@@ -1207,6 +1207,7 @@ void cs35l56_remove(struct cs35l56_private *cs35l56)
        flush_workqueue(cs35l56->dsp_wq);
        destroy_workqueue(cs35l56->dsp_wq);
 
+       pm_runtime_dont_use_autosuspend(cs35l56->base.dev);
        pm_runtime_suspend(cs35l56->base.dev);
        pm_runtime_disable(cs35l56->base.dev);
 
index eeab07c850f9582e918815b44c2698fb5d3995f1..974bae4abfad1cfb8339174c1d861db541380b23 100644 (file)
@@ -344,6 +344,16 @@ static int cs42l42_sdw_update_status(struct sdw_slave *peripheral,
        switch (status) {
        case SDW_SLAVE_ATTACHED:
                dev_dbg(cs42l42->dev, "ATTACHED\n");
+
+               /*
+                * The SoundWire core can report stale ATTACH notifications
+                * if we hard-reset CS42L42 in probe() but it had already been
+                * enumerated. Reject the ATTACH if we haven't yet seen an
+                * UNATTACH report for the device being in reset.
+                */
+               if (cs42l42->sdw_waiting_first_unattach)
+                       break;
+
                /*
                 * Initialise codec, this only needs to be done once.
                 * When resuming from suspend, resume callback will handle re-init of codec,
@@ -354,6 +364,16 @@ static int cs42l42_sdw_update_status(struct sdw_slave *peripheral,
                break;
        case SDW_SLAVE_UNATTACHED:
                dev_dbg(cs42l42->dev, "UNATTACHED\n");
+
+               if (cs42l42->sdw_waiting_first_unattach) {
+                       /*
+                        * SoundWire core has seen that CS42L42 is not on
+                        * the bus so release RESET and wait for ATTACH.
+                        */
+                       cs42l42->sdw_waiting_first_unattach = false;
+                       gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
+               }
+
                break;
        default:
                break;
index a0de0329406a1ff2ea3dc8a29f4ec510335553dd..2961340f15e2ed05d7c551c8d5f68fd557181bdc 100644 (file)
@@ -2320,7 +2320,26 @@ int cs42l42_common_probe(struct cs42l42_private *cs42l42,
 
        if (cs42l42->reset_gpio) {
                dev_dbg(cs42l42->dev, "Found reset GPIO\n");
-               gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
+
+               /*
+                * ACPI can override the default GPIO state we requested
+                * so ensure that we start with RESET low.
+                */
+               gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
+
+               /* Ensure minimum reset pulse width */
+               usleep_range(10, 500);
+
+               /*
+                * On SoundWire keep the chip in reset until we get an UNATTACH
+                * notification from the SoundWire core. This acts as a
+                * synchronization point to reject stale ATTACH notifications
+                * if the chip was already enumerated before we reset it.
+                */
+               if (cs42l42->sdw_peripheral)
+                       cs42l42->sdw_waiting_first_unattach = true;
+               else
+                       gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
        }
        usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
 
index 4bd7b85a5747158ecf808c41d970eaa4c15066ab..7785125b73ab9342f70bb3438d69693b6710688b 100644 (file)
@@ -53,6 +53,7 @@ struct  cs42l42_private {
        u8 stream_use;
        bool hp_adc_up_pending;
        bool suspended;
+       bool sdw_waiting_first_unattach;
        bool init_done;
 };
 
index 1a95c370fc4c9d6687650fe7a06f37d95c884084..5643c666d7d04bf2e507126a7ba4d28430b6925f 100644 (file)
@@ -2077,7 +2077,8 @@ static const struct cs42l43_irq cs42l43_irqs[] = {
 
 static int cs42l43_request_irq(struct cs42l43_codec *priv,
                               struct irq_domain *dom, const char * const name,
-                              unsigned int irq, irq_handler_t handler)
+                              unsigned int irq, irq_handler_t handler,
+                              unsigned long flags)
 {
        int ret;
 
@@ -2087,8 +2088,8 @@ static int cs42l43_request_irq(struct cs42l43_codec *priv,
 
        dev_dbg(priv->dev, "Request IRQ %d for %s\n", ret, name);
 
-       ret = devm_request_threaded_irq(priv->dev, ret, NULL, handler, IRQF_ONESHOT,
-                                       name, priv);
+       ret = devm_request_threaded_irq(priv->dev, ret, NULL, handler,
+                                       IRQF_ONESHOT | flags, name, priv);
        if (ret)
                return dev_err_probe(priv->dev, ret, "Failed to request IRQ %s\n", name);
 
@@ -2124,11 +2125,11 @@ static int cs42l43_shutter_irq(struct cs42l43_codec *priv,
                return 0;
        }
 
-       ret = cs42l43_request_irq(priv, dom, close_name, close_irq, handler);
+       ret = cs42l43_request_irq(priv, dom, close_name, close_irq, handler, IRQF_SHARED);
        if (ret)
                return ret;
 
-       return cs42l43_request_irq(priv, dom, open_name, open_irq, handler);
+       return cs42l43_request_irq(priv, dom, open_name, open_irq, handler, IRQF_SHARED);
 }
 
 static int cs42l43_codec_probe(struct platform_device *pdev)
@@ -2178,7 +2179,8 @@ static int cs42l43_codec_probe(struct platform_device *pdev)
 
        for (i = 0; i < ARRAY_SIZE(cs42l43_irqs); i++) {
                ret = cs42l43_request_irq(priv, dom, cs42l43_irqs[i].name,
-                                         cs42l43_irqs[i].irq, cs42l43_irqs[i].handler);
+                                         cs42l43_irqs[i].irq,
+                                         cs42l43_irqs[i].handler, 0);
                if (ret)
                        goto err_pm;
        }
index 15e1a62b9e571053284e3a2e8e8466fd5faf290f..e8cdc166bdaa99a948b03966d8cf67dbf49e7440 100644 (file)
@@ -2403,13 +2403,11 @@ static irqreturn_t rt5640_irq(int irq, void *data)
        struct rt5640_priv *rt5640 = data;
        int delay = 0;
 
-       if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER) {
-               cancel_delayed_work_sync(&rt5640->jack_work);
+       if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER)
                delay = 100;
-       }
 
        if (rt5640->jack)
-               queue_delayed_work(system_long_wq, &rt5640->jack_work, delay);
+               mod_delayed_work(system_long_wq, &rt5640->jack_work, delay);
 
        return IRQ_HANDLED;
 }
@@ -2565,10 +2563,9 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
        if (jack_data && jack_data->use_platform_clock)
                rt5640->use_platform_clock = jack_data->use_platform_clock;
 
-       ret = devm_request_threaded_irq(component->dev, rt5640->irq,
-                                       NULL, rt5640_irq,
-                                       IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-                                       "rt5640", rt5640);
+       ret = request_irq(rt5640->irq, rt5640_irq,
+                         IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                         "rt5640", rt5640);
        if (ret) {
                dev_warn(component->dev, "Failed to request IRQ %d: %d\n", rt5640->irq, ret);
                rt5640_disable_jack_detect(component);
@@ -2621,14 +2618,14 @@ static void rt5640_enable_hda_jack_detect(
 
        rt5640->jack = jack;
 
-       ret = devm_request_threaded_irq(component->dev, rt5640->irq,
-                                       NULL, rt5640_irq, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
-                                       "rt5640", rt5640);
+       ret = request_irq(rt5640->irq, rt5640_irq,
+                         IRQF_TRIGGER_RISING | IRQF_ONESHOT, "rt5640", rt5640);
        if (ret) {
                dev_warn(component->dev, "Failed to request IRQ %d: %d\n", rt5640->irq, ret);
-               rt5640->irq = -ENXIO;
+               rt5640->jack = NULL;
                return;
        }
+       rt5640->irq_requested = true;
 
        /* sync initial jack state */
        queue_delayed_work(system_long_wq, &rt5640->jack_work, 0);
@@ -2801,12 +2798,12 @@ static int rt5640_suspend(struct snd_soc_component *component)
 {
        struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
 
-       if (rt5640->irq) {
+       if (rt5640->jack) {
                /* disable jack interrupts during system suspend */
                disable_irq(rt5640->irq);
+               rt5640_cancel_work(rt5640);
        }
 
-       rt5640_cancel_work(rt5640);
        snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
        rt5640_reset(component);
        regcache_cache_only(rt5640->regmap, true);
@@ -2829,9 +2826,6 @@ static int rt5640_resume(struct snd_soc_component *component)
        regcache_cache_only(rt5640->regmap, false);
        regcache_sync(rt5640->regmap);
 
-       if (rt5640->irq)
-               enable_irq(rt5640->irq);
-
        if (rt5640->jack) {
                if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER) {
                        snd_soc_component_update_bits(component,
@@ -2859,6 +2853,7 @@ static int rt5640_resume(struct snd_soc_component *component)
                        }
                }
 
+               enable_irq(rt5640->irq);
                queue_delayed_work(system_long_wq, &rt5640->jack_work, 0);
        }
 
index 0a50180750e8815c42040b4e433cd2f0381d3148..7689fe3cc86d657e332b820c94cb87396344ab9d 100644 (file)
@@ -1468,8 +1468,10 @@ static int wm8960_i2c_probe(struct i2c_client *i2c)
        }
 
        wm8960->regmap = devm_regmap_init_i2c(i2c, &wm8960_regmap);
-       if (IS_ERR(wm8960->regmap))
-               return PTR_ERR(wm8960->regmap);
+       if (IS_ERR(wm8960->regmap)) {
+               ret = PTR_ERR(wm8960->regmap);
+               goto bulk_disable;
+       }
 
        if (pdata)
                memcpy(&wm8960->pdata, pdata, sizeof(struct wm8960_data));
@@ -1479,13 +1481,14 @@ static int wm8960_i2c_probe(struct i2c_client *i2c)
        ret = i2c_master_recv(i2c, &val, sizeof(val));
        if (ret >= 0) {
                dev_err(&i2c->dev, "Not wm8960, wm8960 reg can not read by i2c\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto bulk_disable;
        }
 
        ret = wm8960_reset(wm8960->regmap);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to issue reset\n");
-               return ret;
+               goto bulk_disable;
        }
 
        if (wm8960->pdata.shared_lrclk) {
@@ -1494,7 +1497,7 @@ static int wm8960_i2c_probe(struct i2c_client *i2c)
                if (ret != 0) {
                        dev_err(&i2c->dev, "Failed to enable LRCM: %d\n",
                                ret);
-                       return ret;
+                       goto bulk_disable;
                }
        }
 
@@ -1528,7 +1531,13 @@ static int wm8960_i2c_probe(struct i2c_client *i2c)
 
        ret = devm_snd_soc_register_component(&i2c->dev,
                        &soc_component_dev_wm8960, &wm8960_dai, 1);
+       if (ret)
+               goto bulk_disable;
 
+       return 0;
+
+bulk_disable:
+       regulator_bulk_disable(ARRAY_SIZE(wm8960->supplies), wm8960->supplies);
        return ret;
 }
 
index 6fc34f41b1758094acb4ba653eeb1bb023712399..d1b9238d391e81c089e43a85534d77846d77e440 100644 (file)
@@ -687,7 +687,10 @@ int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type,
        struct wm_coeff_ctl *ctl;
        int ret;
 
+       mutex_lock(&dsp->cs_dsp.pwr_lock);
        ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, buf, len);
+       mutex_unlock(&dsp->cs_dsp.pwr_lock);
+
        if (ret < 0)
                return ret;
 
@@ -703,8 +706,14 @@ EXPORT_SYMBOL_GPL(wm_adsp_write_ctl);
 int wm_adsp_read_ctl(struct wm_adsp *dsp, const char *name, int type,
                     unsigned int alg, void *buf, size_t len)
 {
-       return cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(&dsp->cs_dsp, name, type, alg),
-                                     0, buf, len);
+       int ret;
+
+       mutex_lock(&dsp->cs_dsp.pwr_lock);
+       ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(&dsp->cs_dsp, name, type, alg),
+                                    0, buf, len);
+       mutex_unlock(&dsp->cs_dsp.pwr_lock);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(wm_adsp_read_ctl);
 
index 0b58df56f4daa831baffc5dd294bfbc458add70e..aeb81aa61184fbc0889765ac1573a0a23ef3c2c6 100644 (file)
@@ -315,7 +315,7 @@ static int imx_audmix_probe(struct platform_device *pdev)
        if (IS_ERR(priv->cpu_mclk)) {
                ret = PTR_ERR(priv->cpu_mclk);
                dev_err(&cpu_pdev->dev, "failed to get DAI mclk1: %d\n", ret);
-               return -EINVAL;
+               return ret;
        }
 
        priv->audmix_pdev = audmix_pdev;
index d63782b8bdef8f8b27d9669dabdc550cd0445f5a..bb736d45c9e04e5de7de46698d55b1b16b5a8718 100644 (file)
@@ -19,6 +19,7 @@
 static struct snd_pcm_hardware imx_rpmsg_pcm_hardware = {
        .info = SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_BATCH |
                SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_MMAP_VALID |
                SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
index 3c7b95db2eacc182b9d56a71c0847e76a5c910e0..b578f9a32d7f1cd62e9bdf4d84b92063a74c334d 100644 (file)
@@ -89,6 +89,14 @@ static int imx_rpmsg_probe(struct platform_device *pdev)
                            SND_SOC_DAIFMT_NB_NF |
                            SND_SOC_DAIFMT_CBC_CFC;
 
+       /*
+        * i.MX rpmsg sound cards work on codec slave mode. MCLK will be
+        * disabled by CPU DAI driver in hw_free(). Some codec requires MCLK
+        * present at power up/down sequence. So need to set ignore_pmdown_time
+        * to power down codec immediately before MCLK is turned off.
+        */
+       data->dai.ignore_pmdown_time = 1;
+
        /* Optional codec node */
        ret = of_parse_phandle_with_fixed_args(np, "audio-codec", 0, 0, &args);
        if (ret) {
index cb00bc86ac949a5a5592da5a40768271d88e87ba..8876558f19a1bacfd4b7d5b575b25602d885b68a 100644 (file)
@@ -55,6 +55,9 @@ static int avs_create_dai_links(struct device *dev, struct hda_codec *codec, int
                        return -ENOMEM;
 
                dl[i].codecs->name = devm_kstrdup(dev, cname, GFP_KERNEL);
+               if (!dl[i].codecs->name)
+                       return -ENOMEM;
+
                dl[i].codecs->dai_name = pcm->name;
                dl[i].num_codecs = 1;
                dl[i].num_cpus = 1;
index d8688016907525eb80e6dd014e12d2916237b118..bc2f2849ecfbce1f5e12d8cdc7d56858b6c56798 100644 (file)
@@ -112,34 +112,6 @@ static int axg_spdifin_prepare(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int axg_spdifin_startup(struct snd_pcm_substream *substream,
-                              struct snd_soc_dai *dai)
-{
-       struct axg_spdifin *priv = snd_soc_dai_get_drvdata(dai);
-       int ret;
-
-       ret = clk_prepare_enable(priv->refclk);
-       if (ret) {
-               dev_err(dai->dev,
-                       "failed to enable spdifin reference clock\n");
-               return ret;
-       }
-
-       regmap_update_bits(priv->map, SPDIFIN_CTRL0, SPDIFIN_CTRL0_EN,
-                          SPDIFIN_CTRL0_EN);
-
-       return 0;
-}
-
-static void axg_spdifin_shutdown(struct snd_pcm_substream *substream,
-                                struct snd_soc_dai *dai)
-{
-       struct axg_spdifin *priv = snd_soc_dai_get_drvdata(dai);
-
-       regmap_update_bits(priv->map, SPDIFIN_CTRL0, SPDIFIN_CTRL0_EN, 0);
-       clk_disable_unprepare(priv->refclk);
-}
-
 static void axg_spdifin_write_mode_param(struct regmap *map, int mode,
                                         unsigned int val,
                                         unsigned int num_per_reg,
@@ -251,17 +223,32 @@ static int axg_spdifin_dai_probe(struct snd_soc_dai *dai)
        ret = axg_spdifin_sample_mode_config(dai, priv);
        if (ret) {
                dev_err(dai->dev, "mode configuration failed\n");
-               clk_disable_unprepare(priv->pclk);
-               return ret;
+               goto pclk_err;
        }
 
+       ret = clk_prepare_enable(priv->refclk);
+       if (ret) {
+               dev_err(dai->dev,
+                       "failed to enable spdifin reference clock\n");
+               goto pclk_err;
+       }
+
+       regmap_update_bits(priv->map, SPDIFIN_CTRL0, SPDIFIN_CTRL0_EN,
+                          SPDIFIN_CTRL0_EN);
+
        return 0;
+
+pclk_err:
+       clk_disable_unprepare(priv->pclk);
+       return ret;
 }
 
 static int axg_spdifin_dai_remove(struct snd_soc_dai *dai)
 {
        struct axg_spdifin *priv = snd_soc_dai_get_drvdata(dai);
 
+       regmap_update_bits(priv->map, SPDIFIN_CTRL0, SPDIFIN_CTRL0_EN, 0);
+       clk_disable_unprepare(priv->refclk);
        clk_disable_unprepare(priv->pclk);
        return 0;
 }
@@ -270,8 +257,6 @@ static const struct snd_soc_dai_ops axg_spdifin_ops = {
        .probe          = axg_spdifin_dai_probe,
        .remove         = axg_spdifin_dai_remove,
        .prepare        = axg_spdifin_prepare,
-       .startup        = axg_spdifin_startup,
-       .shutdown       = axg_spdifin_shutdown,
 };
 
 static int axg_spdifin_iec958_info(struct snd_kcontrol *kcontrol,
index e29c2fee9521943bd961b5725b30a9024a00e72b..1bd7114c472a8bb8c9032a599b0da385710ee820 100644 (file)
@@ -1303,6 +1303,7 @@ audio_graph:
                if (i >= RSND_MAX_COMPONENT) {
                        dev_info(dev, "reach to max component\n");
                        of_node_put(node);
+                       of_node_put(ports);
                        break;
                }
        }
index eb07238768511a7c7478a6a2556e5a72f0b52ec0..54704250c0a2c43e42ad09ce631953233c444b1e 100644 (file)
@@ -985,6 +985,7 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
 {
        struct snd_soc_dai *cpu_dai;
        struct snd_soc_dai *codec_dai;
+       struct snd_pcm_hw_params tmp_params;
        int i, ret = 0;
 
        snd_soc_dpcm_mutex_assert_held(rtd);
@@ -998,7 +999,6 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
                goto out;
 
        for_each_rtd_codec_dais(rtd, i, codec_dai) {
-               struct snd_pcm_hw_params codec_params;
                unsigned int tdm_mask = snd_soc_dai_tdm_mask_get(codec_dai, substream->stream);
 
                /*
@@ -1019,23 +1019,22 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
                        continue;
 
                /* copy params for each codec */
-               codec_params = *params;
+               tmp_params = *params;
 
                /* fixup params based on TDM slot masks */
                if (tdm_mask)
-                       soc_pcm_codec_params_fixup(&codec_params, tdm_mask);
+                       soc_pcm_codec_params_fixup(&tmp_params, tdm_mask);
 
                ret = snd_soc_dai_hw_params(codec_dai, substream,
-                                           &codec_params);
+                                           &tmp_params);
                if(ret < 0)
                        goto out;
 
-               soc_pcm_set_dai_params(codec_dai, &codec_params);
-               snd_soc_dapm_update_dai(substream, &codec_params, codec_dai);
+               soc_pcm_set_dai_params(codec_dai, &tmp_params);
+               snd_soc_dapm_update_dai(substream, &tmp_params, codec_dai);
        }
 
        for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
-               struct snd_pcm_hw_params cpu_params;
                unsigned int ch_mask = 0;
                int j;
 
@@ -1047,7 +1046,7 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
                        continue;
 
                /* copy params for each cpu */
-               cpu_params = *params;
+               tmp_params = *params;
 
                if (!rtd->dai_link->codec_ch_maps)
                        goto hw_params;
@@ -1062,16 +1061,16 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
 
                /* fixup cpu channel number */
                if (ch_mask)
-                       soc_pcm_codec_params_fixup(&cpu_params, ch_mask);
+                       soc_pcm_codec_params_fixup(&tmp_params, ch_mask);
 
 hw_params:
-               ret = snd_soc_dai_hw_params(cpu_dai, substream, &cpu_params);
+               ret = snd_soc_dai_hw_params(cpu_dai, substream, &tmp_params);
                if (ret < 0)
                        goto out;
 
                /* store the parameters for each DAI */
-               soc_pcm_set_dai_params(cpu_dai, &cpu_params);
-               snd_soc_dapm_update_dai(substream, &cpu_params, cpu_dai);
+               soc_pcm_set_dai_params(cpu_dai, &tmp_params);
+               snd_soc_dapm_update_dai(substream, &tmp_params, cpu_dai);
        }
 
        ret = snd_soc_pcm_component_hw_params(substream, params);
index 11607c5f5d5a82f4c8c97abb7e6582cfca36677c..9c746e4edef71c2e9cfa94b8ed4fc61b888c8c54 100644 (file)
@@ -217,6 +217,7 @@ int snd_soc_dai_is_dummy(struct snd_soc_dai *dai)
                return 1;
        return 0;
 }
+EXPORT_SYMBOL_GPL(snd_soc_dai_is_dummy);
 
 int snd_soc_component_is_dummy(struct snd_soc_component *component)
 {
index 30db685cc5f4b99ae47fe95e9367abc330c2b349..2d1616b81485c53b0f436ef57bcbabaebb03c184 100644 (file)
@@ -486,10 +486,9 @@ int snd_sof_device_remove(struct device *dev)
                snd_sof_ipc_free(sdev);
                snd_sof_free_debug(sdev);
                snd_sof_remove(sdev);
+               sof_ops_free(sdev);
        }
 
-       sof_ops_free(sdev);
-
        /* release firmware */
        snd_sof_fw_unload(sdev);
 
index b84ca58da9d5da72d4158dabd51564f046630fe7..f9412517eaf29be8345c00ad574ed643dd2066d5 100644 (file)
@@ -460,7 +460,7 @@ int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
        /* step 3: wait for IPC DONE bit from ROM */
        ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, chip->ipc_ack, status,
                                            ((status & chip->ipc_ack_mask) == chip->ipc_ack_mask),
-                                           HDA_DSP_REG_POLL_INTERVAL_US, MTL_DSP_PURGE_TIMEOUT_US);
+                                           HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_INIT_TIMEOUT_US);
        if (ret < 0) {
                if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
                        dev_err(sdev->dev, "timeout waiting for purge IPC done\n");
index 02181490f12a6f1b550e0463dcae039161a0993b..95696b3d7c4cfbadb5a3307954a0c9ace19e07cd 100644 (file)
@@ -62,7 +62,6 @@
 #define MTL_DSP_IRQSTS_IPC             BIT(0)
 #define MTL_DSP_IRQSTS_SDW             BIT(6)
 
-#define MTL_DSP_PURGE_TIMEOUT_US       20000000 /* 20s */
 #define MTL_DSP_REG_POLL_INTERVAL_US   10      /* 10 us */
 
 /* Memory windows */
index f2a30cd3137875b69a3f6248d50267dcff24d193..7cb63e6b24dc96f59eea968ae1f718990dedbe18 100644 (file)
@@ -231,7 +231,7 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp,
 
        ret = sof_update_ipc_object(scomp, available_fmt,
                                    SOF_AUDIO_FMT_NUM_TOKENS, swidget->tuples,
-                                   swidget->num_tuples, sizeof(available_fmt), 1);
+                                   swidget->num_tuples, sizeof(*available_fmt), 1);
        if (ret) {
                dev_err(scomp->dev, "Failed to parse audio format token count\n");
                return ret;
index e7ef77012c3586649f364d538c42ab4c89496c48..e5405f854a910c279596b6803c73d9d21b9170c1 100644 (file)
@@ -212,7 +212,8 @@ widget_free:
        sof_widget_free_unlocked(sdev, swidget);
        use_count_decremented = true;
 core_put:
-       snd_sof_dsp_core_put(sdev, swidget->core);
+       if (!use_count_decremented)
+               snd_sof_dsp_core_put(sdev, swidget->core);
 pipe_widget_free:
        if (swidget->id != snd_soc_dapm_scheduler)
                sof_widget_free_unlocked(sdev, swidget->spipe->pipe_widget);
index 1f2c5018bf5aceded1267d64d5974dc8e3495ec5..4737e776d3837d60135523f64e1dc89f298e23e0 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/platform_device.h>
 #include <sound/graph_card.h>
 #include <sound/pcm_params.h>
+#include <sound/soc-dai.h>
 
 #define MAX_PLLA_OUT0_DIV 128
 
@@ -44,6 +45,21 @@ struct tegra_audio_cdata {
        unsigned int plla_out0_rates[NUM_RATE_TYPE];
 };
 
+static bool need_clk_update(struct snd_soc_dai *dai)
+{
+       if (snd_soc_dai_is_dummy(dai) ||
+           !dai->driver->ops ||
+           !dai->driver->name)
+               return false;
+
+       if (strstr(dai->driver->name, "I2S") ||
+           strstr(dai->driver->name, "DMIC") ||
+           strstr(dai->driver->name, "DSPK"))
+               return true;
+
+       return false;
+}
+
 /* Setup PLL clock as per the given sample rate */
 static int tegra_audio_graph_update_pll(struct snd_pcm_substream *substream,
                                        struct snd_pcm_hw_params *params)
@@ -140,19 +156,7 @@ static int tegra_audio_graph_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
        int err;
 
-       /*
-        * This gets called for each DAI link (FE or BE) when DPCM is used.
-        * We may not want to update PLLA rate for each call. So PLLA update
-        * must be restricted to external I/O links (I2S, DMIC or DSPK) since
-        * they actually depend on it. I/O modules update their clocks in
-        * hw_param() of their respective component driver and PLLA rate
-        * update here helps them to derive appropriate rates.
-        *
-        * TODO: When more HW accelerators get added (like sample rate
-        * converter, volume gain controller etc., which don't really
-        * depend on PLLA) we need a better way to filter here.
-        */
-       if (cpu_dai->driver->ops && rtd->dai_link->no_pcm) {
+       if (need_clk_update(cpu_dai)) {
                err = tegra_audio_graph_update_pll(substream, params);
                if (err)
                        return err;
index 49f63f878e6fe8b7acbaa363dfebf3b2114dd753..b5cbf1f195c48cbe16c0da96488880fcad450b10 100644 (file)
@@ -485,7 +485,7 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
        }
 
        usb_make_path(usb_dev, usbpath, sizeof(usbpath));
-       snprintf(card->longname, sizeof(card->longname), "%s %s (%s)",
+       scnprintf(card->longname, sizeof(card->longname), "%s %s (%s)",
                       cdev->vendor_name, cdev->product_name, usbpath);
 
        setup_card(cdev);
index 9105ec623120a964802af82502b247bd9df47051..985b1aea9cdc94bf6687e08c42965d89f84ca8b2 100644 (file)
@@ -1929,7 +1929,6 @@ static int parse_clock_source_unit(struct mixer_build *state, int unitid,
        struct uac_clock_source_descriptor *hdr = _ftr;
        struct usb_mixer_elem_info *cval;
        struct snd_kcontrol *kctl;
-       char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
        int ret;
 
        if (state->mixer->protocol != UAC_VERSION_2)
@@ -1966,10 +1965,9 @@ static int parse_clock_source_unit(struct mixer_build *state, int unitid,
 
        kctl->private_free = snd_usb_mixer_elem_free;
        ret = snd_usb_copy_string_desc(state->chip, hdr->iClockSource,
-                                      name, sizeof(name));
+                                      kctl->id.name, sizeof(kctl->id.name));
        if (ret > 0)
-               snprintf(kctl->id.name, sizeof(kctl->id.name),
-                        "%s Validity", name);
+               append_ctl_name(kctl, " Validity");
        else
                snprintf(kctl->id.name, sizeof(kctl->id.name),
                         "Clock Source %d Validity", hdr->bClockID);
index 9d11bb08667e7a664017a5ec8530e5ff4ade91f9..d260be8cb6bc03e8c5c2b2a3dc5ff5759ff2588d 100644 (file)
@@ -3205,8 +3205,8 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer)
        /* Add input phantom controls */
        if (info->inputs_per_phantom == 1) {
                for (i = 0; i < info->phantom_count; i++) {
-                       snprintf(s, sizeof(s), fmt, i + 1,
-                                "Phantom Power", "Switch");
+                       scnprintf(s, sizeof(s), fmt, i + 1,
+                                 "Phantom Power", "Switch");
                        err = scarlett2_add_new_ctl(
                                mixer, &scarlett2_phantom_ctl,
                                i, 1, s, &private->phantom_ctls[i]);
@@ -3218,8 +3218,8 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer)
                        int from = i * info->inputs_per_phantom + 1;
                        int to = (i + 1) * info->inputs_per_phantom;
 
-                       snprintf(s, sizeof(s), fmt2, from, to,
-                                "Phantom Power", "Switch");
+                       scnprintf(s, sizeof(s), fmt2, from, to,
+                                 "Phantom Power", "Switch");
                        err = scarlett2_add_new_ctl(
                                mixer, &scarlett2_phantom_ctl,
                                i, 1, s, &private->phantom_ctls[i]);
index 63b0398c327656b543cca5962bb8991ee8b287cd..55ecf766ca6780447d1ed9103328366bfa7f57b2 100644 (file)
@@ -483,7 +483,7 @@ int xen_snd_front_cfg_card(struct xen_snd_front_info *front_info,
        *stream_cnt = 0;
        num_devices = 0;
        do {
-               snprintf(node, sizeof(node), "%d", num_devices);
+               scnprintf(node, sizeof(node), "%d", num_devices);
                if (!xenbus_exists(XBT_NIL, xb_dev->nodename, node))
                        break;
 
index 71e54b1e379645fd8ce2233801f3e2c619699ee6..2f882d5cb30f5c014af5deec2738f8460dcc23ad 100644 (file)
@@ -38,7 +38,7 @@ asm(                                                  \
        ____BTF_ID(symbol)
 
 #define __ID(prefix) \
-       __PASTE(prefix, __COUNTER__)
+       __PASTE(__PASTE(prefix, __COUNTER__), __LINE__)
 
 /*
  * The BTF_ID defines unique symbol for each ID pointing
index a03d9bba515148a72192cf2b9cddab32d047858d..f3c82ab5b14cd77819030096b81e0b67cba0df1d 100644 (file)
@@ -11,8 +11,6 @@
 
 #define PHYS_ADDR_MAX  (~(phys_addr_t)0)
 
-#define __ALIGN_KERNEL(x, a)           __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
-#define __ALIGN_KERNEL_MASK(x, mask)   (((x) + (mask)) & ~(mask))
 #define ALIGN(x, a)                    __ALIGN_KERNEL((x), (a))
 #define ALIGN_DOWN(x, a)               __ALIGN_KERNEL((x) - ((a) - 1), (a))
 
@@ -29,7 +27,7 @@ static inline void *phys_to_virt(unsigned long address)
        return __va(address);
 }
 
-void reserve_bootmem_region(phys_addr_t start, phys_addr_t end);
+void reserve_bootmem_region(phys_addr_t start, phys_addr_t end, int nid);
 
 static inline void totalram_pages_inc(void)
 {
index 102fd9217f1f9b96438f14e7d9ef643d123ebc43..f6bc226af0c1d1c4d26c1c2d3f7a963c34c728eb 100644 (file)
@@ -1,4 +1,6 @@
 #ifndef _TOOLS_INCLUDE_LINUX_SEQ_FILE_H
 #define _TOOLS_INCLUDE_LINUX_SEQ_FILE_H
 
+struct seq_file;
+
 #endif /* _TOOLS_INCLUDE_LINUX_SEQ_FILE_H */
index 8790b3962e4b85f22593f8f9c9f8d94eaf6981f3..0448700890f77d9a4fffa6fed5c17aa02b9f718b 100644 (file)
@@ -1962,7 +1962,9 @@ union bpf_attr {
  *             performed again, if the helper is used in combination with
  *             direct packet access.
  *     Return
- *             0 on success, or a negative error in case of failure.
+ *             0 on success, or a negative error in case of failure. Positive
+ *             error indicates a potential drop or congestion in the target
+ *             device. The particular positive error codes are not defined.
  *
  * u64 bpf_get_current_pid_tgid(void)
  *     Description
index 1384090530dbe3e7e0c018c833aeacdf2f95b720..e308d1ba664ef9366edc5f1412dac8659ad3a9bb 100644 (file)
@@ -4333,7 +4333,8 @@ static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn
                        continue;
                }
 
-               if (insn_func(dest) && insn_func(dest) == insn_func(insn)) {
+               if (insn_func(dest) && insn_func(insn) &&
+                   insn_func(dest)->pfunc == insn_func(insn)->pfunc) {
                        /*
                         * Anything from->to self is either _THIS_IP_ or
                         * IRET-to-self.
index fdb7f5db730822e93d7732026218609cda4a054c..f6c6e5474c3afbcb238eae15e71cadb4c986f411 100644 (file)
@@ -20,4 +20,8 @@ void memblock_free_pages(struct page *page, unsigned long pfn,
 {
 }
 
+static inline void accept_memory(phys_addr_t start, phys_addr_t end)
+{
+}
+
 #endif
index 7b0909e8b759d446aa90931f062230d9a5d9e091..d3d58851864e7c7f842e201a1032bf195d50bd7a 100644 (file)
@@ -11,7 +11,7 @@ struct pglist_data *next_online_pgdat(struct pglist_data *pgdat)
        return NULL;
 }
 
-void reserve_bootmem_region(phys_addr_t start, phys_addr_t end)
+void reserve_bootmem_region(phys_addr_t start, phys_addr_t end, int nid)
 {
 }
 
index 411647094cc37f832ecc69c829a57036a800c9db..57bf2688edfd68ca8dbc5724da1e78aff9897e59 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
+#include "basic_api.h"
 #include <string.h>
 #include <linux/memblock.h>
-#include "basic_api.h"
 
 #define EXPECTED_MEMBLOCK_REGIONS                      128
 #define FUNC_ADD                                       "memblock_add"
index 4f23302ee6779a4b6b7e7007e2fea98b60094a4c..b5ec59aa62d72ab2ad3f51ffd5d2b4fb6722a8a3 100644 (file)
@@ -5,6 +5,7 @@
 #include <stdlib.h>
 #include <assert.h>
 #include <linux/types.h>
+#include <linux/seq_file.h>
 #include <linux/memblock.h>
 #include <linux/sizes.h>
 #include <linux/printk.h>
index d7aafe5a1993aaf45aa1c7b237db72a15a27f224..2f1685a3eae14221610a8c861ee4d4d118186ae5 100644 (file)
@@ -431,7 +431,6 @@ long conf_get_long(snd_config_t *root, const char *key1, const char *key2, long
 int conf_get_bool(snd_config_t *root, const char *key1, const char *key2, int def)
 {
        snd_config_t *cfg;
-       long l;
        int ret;
 
        if (!root)
index c95d63e553f4d2eec044968c9c36d77313d570c8..21e482b23f5028f6e35fae82d4416a821659048e 100644 (file)
@@ -188,7 +188,7 @@ static int wait_for_event(struct ctl_data *ctl, int timeout)
 {
        unsigned short revents;
        snd_ctl_event_t *event;
-       int count, err;
+       int err;
        unsigned int mask = 0;
        unsigned int ev_id;
 
@@ -430,7 +430,6 @@ static bool strend(const char *haystack, const char *needle)
 static void test_ctl_name(struct ctl_data *ctl)
 {
        bool name_ok = true;
-       bool check;
 
        ksft_print_msg("%d.%d %s\n", ctl->card->card, ctl->elem,
                       ctl->name);
@@ -863,7 +862,6 @@ static bool test_ctl_write_invalid_value(struct ctl_data *ctl,
                                         snd_ctl_elem_value_t *val)
 {
        int err;
-       long val_read;
 
        /* Ideally this will fail... */
        err = snd_ctl_elem_write(ctl->card->handle, val);
@@ -883,8 +881,7 @@ static bool test_ctl_write_invalid_value(struct ctl_data *ctl,
 
 static bool test_ctl_write_invalid_boolean(struct ctl_data *ctl)
 {
-       int err, i;
-       long val_read;
+       int i;
        bool fail = false;
        snd_ctl_elem_value_t *val;
        snd_ctl_elem_value_alloca(&val);
@@ -994,8 +991,7 @@ static bool test_ctl_write_invalid_integer64(struct ctl_data *ctl)
 
 static bool test_ctl_write_invalid_enumerated(struct ctl_data *ctl)
 {
-       int err, i;
-       unsigned int val_read;
+       int i;
        bool fail = false;
        snd_ctl_elem_value_t *val;
        snd_ctl_elem_value_alloca(&val);
@@ -1027,7 +1023,6 @@ static bool test_ctl_write_invalid_enumerated(struct ctl_data *ctl)
 static void test_ctl_write_invalid(struct ctl_data *ctl)
 {
        bool pass;
-       int err;
 
        /* If the control is turned off let's be polite */
        if (snd_ctl_elem_info_is_inactive(ctl->info)) {
index 2f5e3c462194f0ba8b871f018c933e4351d17f70..c0a39818c5a4bbf99191973a5cf61a0756ee4d90 100644 (file)
@@ -257,7 +257,7 @@ static void find_pcms(void)
 static void test_pcm_time(struct pcm_data *data, enum test_class class,
                          const char *test_name, snd_config_t *pcm_cfg)
 {
-       char name[64], key[128], msg[256];
+       char name[64], msg[256];
        const int duration_s = 2, margin_ms = 100;
        const int duration_ms = duration_s * 1000;
        const char *cs;
@@ -567,7 +567,7 @@ int main(void)
 {
        struct card_data *card;
        struct pcm_data *pcm;
-       snd_config_t *global_config, *cfg, *pcm_cfg;
+       snd_config_t *global_config, *cfg;
        int num_pcm_tests = 0, num_tests, num_std_pcm_tests;
        int ret;
        void *thread_ret;
index 357adc722cbae846657e6f4149447cf71db56ff2..a52ecd43dbe30f81aec81aa8b384c85023e94350 100644 (file)
@@ -313,7 +313,6 @@ TEST_F(pcmtest, ni_playback) {
  */
 TEST_F(pcmtest, reset_ioctl) {
        snd_pcm_t *handle;
-       unsigned char *it;
        int test_res;
        struct pcmtest_test_params *params = &self->params;
 
index 7f768d335698764527bb997413bcf63beef35991..3babaf3eee5c455ddbc5cf23d49b56ae02e0e3c9 100644 (file)
@@ -1,14 +1,8 @@
 bpf_cookie/multi_kprobe_attach_api               # kprobe_multi_link_api_subtest:FAIL:fentry_raw_skel_load unexpected error: -3
 bpf_cookie/multi_kprobe_link_api                 # kprobe_multi_link_api_subtest:FAIL:fentry_raw_skel_load unexpected error: -3
 fexit_sleep                                      # The test never returns. The remaining tests cannot start.
-kprobe_multi_bench_attach                        # bpf_program__attach_kprobe_multi_opts unexpected error: -95
-kprobe_multi_test/attach_api_addrs               # bpf_program__attach_kprobe_multi_opts unexpected error: -95
-kprobe_multi_test/attach_api_pattern             # bpf_program__attach_kprobe_multi_opts unexpected error: -95
-kprobe_multi_test/attach_api_syms                # bpf_program__attach_kprobe_multi_opts unexpected error: -95
-kprobe_multi_test/bench_attach                   # bpf_program__attach_kprobe_multi_opts unexpected error: -95
-kprobe_multi_test/link_api_addrs                 # link_fd unexpected link_fd: actual -95 < expected 0
-kprobe_multi_test/link_api_syms                  # link_fd unexpected link_fd: actual -95 < expected 0
-kprobe_multi_test/skel_api                       # libbpf: failed to load BPF skeleton 'kprobe_multi': -3
+kprobe_multi_bench_attach                        # needs CONFIG_FPROBE
+kprobe_multi_test                                # needs CONFIG_FPROBE
 module_attach                                    # prog 'kprobe_multi': failed to auto-attach: -95
 fentry_test/fentry_many_args                     # fentry_many_args:FAIL:fentry_many_args_attach unexpected error: -524
 fexit_test/fexit_many_args                       # fexit_many_args:FAIL:fexit_many_args_attach unexpected error: -524
index 1c7584e8dd9ea969f1f4cb15516425861d0dc9aa..e41eb33b27046c61007ba8a7cbbc44aa199efcfc 100644 (file)
@@ -4,6 +4,7 @@ CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
 CONFIG_BPF=y
 CONFIG_BPF_EVENTS=y
 CONFIG_BPF_JIT=y
+CONFIG_BPF_KPROBE_OVERRIDE=y
 CONFIG_BPF_LIRC_MODE2=y
 CONFIG_BPF_LSM=y
 CONFIG_BPF_STREAM_PARSER=y
index b650b2e617b8fe8d9526d4a27d0fe19037838032..2e70a6048278459e889574972ce29221510221a3 100644 (file)
@@ -20,7 +20,6 @@ CONFIG_BLK_DEV_THROTTLING=y
 CONFIG_BONDING=y
 CONFIG_BOOTTIME_TRACING=y
 CONFIG_BPF_JIT_ALWAYS_ON=y
-CONFIG_BPF_KPROBE_OVERRIDE=y
 CONFIG_BPF_PRELOAD=y
 CONFIG_BPF_PRELOAD_UMD=y
 CONFIG_BPFILTER=y
index 3b77d8a422dbf6ad4d4ebf990f69c5e1ba0e482f..261228eb68e810ce096407c1d80dde41ca398c37 100644 (file)
@@ -24,6 +24,7 @@ void test_empty_skb(void)
                int *ifindex;
                int err;
                int ret;
+               int lwt_egress_ret; /* expected retval at lwt/egress */
                bool success_on_tc;
        } tests[] = {
                /* Empty packets are always rejected. */
@@ -57,6 +58,7 @@ void test_empty_skb(void)
                        .data_size_in = sizeof(eth_hlen),
                        .ifindex = &veth_ifindex,
                        .ret = -ERANGE,
+                       .lwt_egress_ret = -ERANGE,
                        .success_on_tc = true,
                },
                {
@@ -70,6 +72,7 @@ void test_empty_skb(void)
                        .data_size_in = sizeof(eth_hlen),
                        .ifindex = &ipip_ifindex,
                        .ret = -ERANGE,
+                       .lwt_egress_ret = -ERANGE,
                },
 
                /* ETH_HLEN+1-sized packet should be redirected. */
@@ -79,6 +82,7 @@ void test_empty_skb(void)
                        .data_in = eth_hlen_pp,
                        .data_size_in = sizeof(eth_hlen_pp),
                        .ifindex = &veth_ifindex,
+                       .lwt_egress_ret = 1, /* veth_xmit NET_XMIT_DROP */
                },
                {
                        .msg = "ipip ETH_HLEN+1 packet ingress",
@@ -108,8 +112,12 @@ void test_empty_skb(void)
 
        for (i = 0; i < ARRAY_SIZE(tests); i++) {
                bpf_object__for_each_program(prog, bpf_obj->obj) {
-                       char buf[128];
+                       bool at_egress = strstr(bpf_program__name(prog), "egress") != NULL;
                        bool at_tc = !strncmp(bpf_program__section_name(prog), "tc", 2);
+                       int expected_ret;
+                       char buf[128];
+
+                       expected_ret = at_egress && !at_tc ? tests[i].lwt_egress_ret : tests[i].ret;
 
                        tattr.data_in = tests[i].data_in;
                        tattr.data_size_in = tests[i].data_size_in;
@@ -128,7 +136,7 @@ void test_empty_skb(void)
                        if (at_tc && tests[i].success_on_tc)
                                ASSERT_GE(bpf_obj->bss->ret, 0, buf);
                        else
-                               ASSERT_EQ(bpf_obj->bss->ret, tests[i].ret, buf);
+                               ASSERT_EQ(bpf_obj->bss->ret, expected_ret, buf);
                }
        }
 
index 179fe300534f5c56501544e70468ec4a514a545f..4041cfa670eb4c0448baf5aefa4f35ba7f87651a 100644 (file)
@@ -3,6 +3,7 @@
 #include "kprobe_multi.skel.h"
 #include "trace_helpers.h"
 #include "kprobe_multi_empty.skel.h"
+#include "kprobe_multi_override.skel.h"
 #include "bpf/libbpf_internal.h"
 #include "bpf/hashmap.h"
 
@@ -453,6 +454,40 @@ cleanup:
        }
 }
 
+static void test_attach_override(void)
+{
+       struct kprobe_multi_override *skel = NULL;
+       struct bpf_link *link = NULL;
+
+       skel = kprobe_multi_override__open_and_load();
+       if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load"))
+               goto cleanup;
+
+       /* The test_override calls bpf_override_return so it should fail
+        * to attach to bpf_fentry_test1 function, which is not on error
+        * injection list.
+        */
+       link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_override,
+                                                    "bpf_fentry_test1", NULL);
+       if (!ASSERT_ERR_PTR(link, "override_attached_bpf_fentry_test1")) {
+               bpf_link__destroy(link);
+               goto cleanup;
+       }
+
+       /* The should_fail_bio function is on error injection list,
+        * attach should succeed.
+        */
+       link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_override,
+                                                    "should_fail_bio", NULL);
+       if (!ASSERT_OK_PTR(link, "override_attached_should_fail_bio"))
+               goto cleanup;
+
+       bpf_link__destroy(link);
+
+cleanup:
+       kprobe_multi_override__destroy(skel);
+}
+
 void serial_test_kprobe_multi_bench_attach(void)
 {
        if (test__start_subtest("kernel"))
@@ -480,4 +515,6 @@ void test_kprobe_multi_test(void)
                test_attach_api_syms();
        if (test__start_subtest("attach_api_fails"))
                test_attach_api_fails();
+       if (test__start_subtest("attach_override"))
+               test_attach_override();
 }
diff --git a/tools/testing/selftests/bpf/prog_tests/test_bpf_ma.c b/tools/testing/selftests/bpf/prog_tests/test_bpf_ma.c
new file mode 100644 (file)
index 0000000..0cca4e8
--- /dev/null
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2023. Huawei Technologies Co., Ltd */
+#define _GNU_SOURCE
+#include <sched.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <bpf/btf.h>
+#include <test_progs.h>
+
+#include "test_bpf_ma.skel.h"
+
+void test_test_bpf_ma(void)
+{
+       struct test_bpf_ma *skel;
+       struct btf *btf;
+       int i, err;
+
+       skel = test_bpf_ma__open();
+       if (!ASSERT_OK_PTR(skel, "open"))
+               return;
+
+       btf = bpf_object__btf(skel->obj);
+       if (!ASSERT_OK_PTR(btf, "btf"))
+               goto out;
+
+       for (i = 0; i < ARRAY_SIZE(skel->rodata->data_sizes); i++) {
+               char name[32];
+               int id;
+
+               snprintf(name, sizeof(name), "bin_data_%u", skel->rodata->data_sizes[i]);
+               id = btf__find_by_name_kind(btf, name, BTF_KIND_STRUCT);
+               if (!ASSERT_GT(id, 0, "bin_data"))
+                       goto out;
+               skel->rodata->data_btf_ids[i] = id;
+       }
+
+       err = test_bpf_ma__load(skel);
+       if (!ASSERT_OK(err, "load"))
+               goto out;
+
+       err = test_bpf_ma__attach(skel);
+       if (!ASSERT_OK(err, "attach"))
+               goto out;
+
+       skel->bss->pid = getpid();
+       usleep(1);
+       ASSERT_OK(skel->bss->err, "test error");
+out:
+       test_bpf_ma__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_dev_bound_only.c b/tools/testing/selftests/bpf/prog_tests/xdp_dev_bound_only.c
new file mode 100644 (file)
index 0000000..7dd18c6
--- /dev/null
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <net/if.h>
+#include <test_progs.h>
+#include <network_helpers.h>
+
+#define LOCAL_NETNS "xdp_dev_bound_only_netns"
+
+static int load_dummy_prog(char *name, __u32 ifindex, __u32 flags)
+{
+       struct bpf_insn insns[] = { BPF_MOV64_IMM(BPF_REG_0, 0), BPF_EXIT_INSN() };
+       LIBBPF_OPTS(bpf_prog_load_opts, opts);
+
+       opts.prog_flags = flags;
+       opts.prog_ifindex = ifindex;
+       return bpf_prog_load(BPF_PROG_TYPE_XDP, name, "GPL", insns, ARRAY_SIZE(insns), &opts);
+}
+
+/* A test case for bpf_offload_netdev->offload handling bug:
+ * - create a veth device (does not support offload);
+ * - create a device bound XDP program with BPF_F_XDP_DEV_BOUND_ONLY flag
+ *   (such programs are not offloaded);
+ * - create a device bound XDP program without flags (such programs are offloaded).
+ * This might lead to 'BUG: kernel NULL pointer dereference'.
+ */
+void test_xdp_dev_bound_only_offdev(void)
+{
+       struct nstoken *tok = NULL;
+       __u32 ifindex;
+       int fd1 = -1;
+       int fd2 = -1;
+
+       SYS(out, "ip netns add " LOCAL_NETNS);
+       tok = open_netns(LOCAL_NETNS);
+       if (!ASSERT_OK_PTR(tok, "open_netns"))
+               goto out;
+       SYS(out, "ip link add eth42 type veth");
+       ifindex = if_nametoindex("eth42");
+       if (!ASSERT_NEQ(ifindex, 0, "if_nametoindex")) {
+               perror("if_nametoindex");
+               goto out;
+       }
+       fd1 = load_dummy_prog("dummy1", ifindex, BPF_F_XDP_DEV_BOUND_ONLY);
+       if (!ASSERT_GE(fd1, 0, "load_dummy_prog #1")) {
+               perror("load_dummy_prog #1");
+               goto out;
+       }
+       /* Program with ifindex is considered offloaded, however veth
+        * does not support offload => error should be reported.
+        */
+       fd2 = load_dummy_prog("dummy2", ifindex, 0);
+       ASSERT_EQ(fd2, -EINVAL, "load_dummy_prog #2 (offloaded)");
+
+out:
+       close(fd1);
+       close(fd2);
+       close_netns(tok);
+       /* eth42 was added inside netns, removing the netns will
+        * also remove eth42 veth pair.
+        */
+       SYS_NOFAIL("ip netns del " LOCAL_NETNS);
+}
diff --git a/tools/testing/selftests/bpf/progs/kprobe_multi_override.c b/tools/testing/selftests/bpf/progs/kprobe_multi_override.c
new file mode 100644 (file)
index 0000000..28f8487
--- /dev/null
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+char _license[] SEC("license") = "GPL";
+
+SEC("kprobe.multi")
+int test_override(struct pt_regs *ctx)
+{
+       bpf_override_return(ctx, 123);
+       return 0;
+}
diff --git a/tools/testing/selftests/bpf/progs/test_bpf_ma.c b/tools/testing/selftests/bpf/progs/test_bpf_ma.c
new file mode 100644 (file)
index 0000000..ecde41a
--- /dev/null
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2023. Huawei Technologies Co., Ltd */
+#include <vmlinux.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_helpers.h>
+
+#include "bpf_experimental.h"
+#include "bpf_misc.h"
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+struct generic_map_value {
+       void *data;
+};
+
+char _license[] SEC("license") = "GPL";
+
+const unsigned int data_sizes[] = {8, 16, 32, 64, 96, 128, 192, 256, 512, 1024, 2048, 4096};
+const volatile unsigned int data_btf_ids[ARRAY_SIZE(data_sizes)] = {};
+
+int err = 0;
+int pid = 0;
+
+#define DEFINE_ARRAY_WITH_KPTR(_size) \
+       struct bin_data_##_size { \
+               char data[_size - sizeof(void *)]; \
+       }; \
+       struct map_value_##_size { \
+               struct bin_data_##_size __kptr * data; \
+               /* To emit BTF info for bin_data_xx */ \
+               struct bin_data_##_size not_used; \
+       }; \
+       struct { \
+               __uint(type, BPF_MAP_TYPE_ARRAY); \
+               __type(key, int); \
+               __type(value, struct map_value_##_size); \
+               __uint(max_entries, 128); \
+       } array_##_size SEC(".maps");
+
+static __always_inline void batch_alloc_free(struct bpf_map *map, unsigned int batch,
+                                            unsigned int idx)
+{
+       struct generic_map_value *value;
+       unsigned int i, key;
+       void *old, *new;
+
+       for (i = 0; i < batch; i++) {
+               key = i;
+               value = bpf_map_lookup_elem(map, &key);
+               if (!value) {
+                       err = 1;
+                       return;
+               }
+               new = bpf_obj_new_impl(data_btf_ids[idx], NULL);
+               if (!new) {
+                       err = 2;
+                       return;
+               }
+               old = bpf_kptr_xchg(&value->data, new);
+               if (old) {
+                       bpf_obj_drop(old);
+                       err = 3;
+                       return;
+               }
+       }
+       for (i = 0; i < batch; i++) {
+               key = i;
+               value = bpf_map_lookup_elem(map, &key);
+               if (!value) {
+                       err = 4;
+                       return;
+               }
+               old = bpf_kptr_xchg(&value->data, NULL);
+               if (!old) {
+                       err = 5;
+                       return;
+               }
+               bpf_obj_drop(old);
+       }
+}
+
+#define CALL_BATCH_ALLOC_FREE(size, batch, idx) \
+       batch_alloc_free((struct bpf_map *)(&array_##size), batch, idx)
+
+DEFINE_ARRAY_WITH_KPTR(8);
+DEFINE_ARRAY_WITH_KPTR(16);
+DEFINE_ARRAY_WITH_KPTR(32);
+DEFINE_ARRAY_WITH_KPTR(64);
+DEFINE_ARRAY_WITH_KPTR(96);
+DEFINE_ARRAY_WITH_KPTR(128);
+DEFINE_ARRAY_WITH_KPTR(192);
+DEFINE_ARRAY_WITH_KPTR(256);
+DEFINE_ARRAY_WITH_KPTR(512);
+DEFINE_ARRAY_WITH_KPTR(1024);
+DEFINE_ARRAY_WITH_KPTR(2048);
+DEFINE_ARRAY_WITH_KPTR(4096);
+
+SEC("fentry/" SYS_PREFIX "sys_nanosleep")
+int test_bpf_mem_alloc_free(void *ctx)
+{
+       if ((u32)bpf_get_current_pid_tgid() != pid)
+               return 0;
+
+       /* Alloc 128 8-bytes objects in batch to trigger refilling,
+        * then free 128 8-bytes objects in batch to trigger freeing.
+        */
+       CALL_BATCH_ALLOC_FREE(8, 128, 0);
+       CALL_BATCH_ALLOC_FREE(16, 128, 1);
+       CALL_BATCH_ALLOC_FREE(32, 128, 2);
+       CALL_BATCH_ALLOC_FREE(64, 128, 3);
+       CALL_BATCH_ALLOC_FREE(96, 128, 4);
+       CALL_BATCH_ALLOC_FREE(128, 128, 5);
+       CALL_BATCH_ALLOC_FREE(192, 128, 6);
+       CALL_BATCH_ALLOC_FREE(256, 128, 7);
+       CALL_BATCH_ALLOC_FREE(512, 64, 8);
+       CALL_BATCH_ALLOC_FREE(1024, 32, 9);
+       CALL_BATCH_ALLOC_FREE(2048, 16, 10);
+       CALL_BATCH_ALLOC_FREE(4096, 8, 11);
+
+       return 0;
+}
index 31f1c935cd07d2b8f19398912e59433fd558420d..98107e0452d338aee8e2f722e939dab95b6e0e52 100644 (file)
@@ -1880,7 +1880,7 @@ int main(int argc, char **argv)
                }
        }
 
-       get_unpriv_disabled();
+       unpriv_disabled = get_unpriv_disabled();
        if (unpriv && unpriv_disabled) {
                printf("Cannot run as unprivileged user with sysctl %s.\n",
                       UNPRIV_SYSCTL);
index 20839f8e43f2a8a51d1f9472436ddc362e87bf3a..71ec34bf1501e275cbf229861dc6daad59fd905f 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-or-later
 
-CFLAGS += -Wall -O2 -g -fsanitize=address -fsanitize=undefined $(KHDR_INCLUDES)
+CFLAGS += -Wall -O2 -g -fsanitize=address -fsanitize=undefined -static-libasan $(KHDR_INCLUDES)
 TEST_GEN_PROGS := fchmodat2_test
 
 include ../lib.mk
index cb5f18c06593d4ee051d0f9d0bba098dde3ea19e..c778d4dcc17e58523193ffad46a79212b3e721cd 100755 (executable)
@@ -31,6 +31,9 @@ err_ret=1
 # kselftest skip code is 4
 err_skip=4
 
+# umount required
+UMOUNT_DIR=""
+
 # cgroup RT scheduling prevents chrt commands from succeeding, which
 # induces failures in test wakeup tests.  Disable for the duration of
 # the tests.
@@ -45,6 +48,9 @@ setup() {
 
 cleanup() {
   echo $sched_rt_runtime_orig > $sched_rt_runtime
+  if [ -n "${UMOUNT_DIR}" ]; then
+    umount ${UMOUNT_DIR} ||:
+  fi
 }
 
 errexit() { # message
@@ -124,6 +130,7 @@ parse_opts() { # opts
     ;;
     --logdir|-l)
       LOG_DIR=$2
+      LINK_PTR=
       shift 2
     ;;
     *.tc)
@@ -160,11 +167,13 @@ if [ -z "$TRACING_DIR" ]; then
            mount -t tracefs nodev /sys/kernel/tracing ||
              errexit "Failed to mount /sys/kernel/tracing"
            TRACING_DIR="/sys/kernel/tracing"
+           UMOUNT_DIR=${TRACING_DIR}
        # If debugfs exists, then so does /sys/kernel/debug
        elif [ -d "/sys/kernel/debug" ]; then
            mount -t debugfs nodev /sys/kernel/debug ||
              errexit "Failed to mount /sys/kernel/debug"
            TRACING_DIR="/sys/kernel/debug/tracing"
+           UMOUNT_DIR=${TRACING_DIR}
        else
            err_ret=$err_skip
            errexit "debugfs and tracefs are not configured in this kernel"
@@ -181,7 +190,10 @@ fi
 TOP_DIR=`absdir $0`
 TEST_DIR=$TOP_DIR/test.d
 TEST_CASES=`find_testcases $TEST_DIR`
-LOG_DIR=$TOP_DIR/logs/`date +%Y%m%d-%H%M%S`/
+LOG_TOP_DIR=$TOP_DIR/logs
+LOG_DATE=`date +%Y%m%d-%H%M%S`
+LOG_DIR=$LOG_TOP_DIR/$LOG_DATE/
+LINK_PTR=$LOG_TOP_DIR/latest
 KEEP_LOG=0
 KTAP=0
 DEBUG=0
@@ -207,6 +219,10 @@ else
   LOG_FILE=$LOG_DIR/ftracetest.log
   mkdir -p $LOG_DIR || errexit "Failed to make a log directory: $LOG_DIR"
   date > $LOG_FILE
+  if [ "x-$LINK_PTR" != "x-" ]; then
+    unlink $LINK_PTR
+    ln -fs $LOG_DATE $LINK_PTR
+  fi
 fi
 
 # Define text colors
index 0eb47fbb3f44d75d8fafe30af769cf015f7ecad0..42422e4251078729bb773d859283a0954c656f27 100644 (file)
@@ -39,7 +39,7 @@ instance_read() {
 
 instance_set() {
         while :; do
-                echo 1 > foo/events/sched/sched_switch
+                echo 1 > foo/events/sched/sched_switch/enable
         done 2> /dev/null
 }
 
index 213d890ed1886eaa175bc040cb16e0e49aedf496..174376ddbc6c7ab5f0563d4d60613aecce856ee9 100644 (file)
@@ -1,7 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test inter-event histogram trigger trace action with dynamic string param
-# requires: set_event synthetic_events events/sched/sched_process_exec/hist "char name[]' >> synthetic_events":README ping:program
+# requires: set_event synthetic_events events/sched/sched_process_exec/hist "' >> synthetic_events":README ping:program
 
 fail() { #msg
     echo $1
index 955e3ceea44b5b0a3b191eb8f64b4c44ac53707f..b927ee54c02da5959cf400599f98296ebc2c6518 100644 (file)
@@ -1,7 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test synthetic_events syntax parser errors
-# requires: synthetic_events error_log "char name[]' >> synthetic_events":README
+# requires: synthetic_events error_log "' >> synthetic_events":README
 
 check_error() { # command-with-error-pos-by-^
     ftrace_errlog_check 'synthetic_events' "$1" 'synthetic_events'
index 261c73cab41b1d8376da3818e7420897e7583353..cd2fb43eea61ee5ab182783a2706099e321cf956 100644 (file)
@@ -36,7 +36,8 @@ tap_timeout()
 {
        # Make sure tests will time out if utility is available.
        if [ -x /usr/bin/timeout ] ; then
-               /usr/bin/timeout --foreground "$kselftest_timeout" $1
+               /usr/bin/timeout --foreground "$kselftest_timeout" \
+                       /usr/bin/timeout "$kselftest_timeout" $1
        else
                $1
        fi
index 4bc14d9e8ff1d07a11e77d6af7c636b34ed77bf9..de59cc8f03c3f1ad9867a1e19505b657cdfc1d7d 100755 (executable)
@@ -46,11 +46,11 @@ fi
 print_targets=0
 
 while getopts "p" arg; do
-    case $arg in
-        p)
+       case $arg in
+               p)
                print_targets=1
        shift;;
-    esac
+       esac
 done
 
 if [ $# -eq 0 ]
@@ -92,6 +92,10 @@ pass_cnt=0
 # Get all TARGETS from selftests Makefile
 targets=$(grep -E "^TARGETS +|^TARGETS =" Makefile | cut -d "=" -f2)
 
+# Initially, in LDLIBS related lines, the dep checker needs
+# to ignore lines containing the following strings:
+filter="\$(VAR_LDLIBS)\|pkg-config\|PKG_CONFIG\|IOURING_EXTRA_LIBS"
+
 # Single test case
 if [ $# -eq 2 ]
 then
@@ -100,6 +104,8 @@ then
        l1_test $test
        l2_test $test
        l3_test $test
+       l4_test $test
+       l5_test $test
 
        print_results $1 $2
        exit $?
@@ -113,7 +119,7 @@ fi
 # Append space at the end of the list to append more tests.
 
 l1_tests=$(grep -r --include=Makefile "^LDLIBS" | \
-               grep -v "VAR_LDLIBS" | awk -F: '{print $1}')
+               grep -v "$filter" | awk -F: '{print $1}' | uniq)
 
 # Level 2: LDLIBS set dynamically.
 #
@@ -126,7 +132,7 @@ l1_tests=$(grep -r --include=Makefile "^LDLIBS" | \
 # Append space at the end of the list to append more tests.
 
 l2_tests=$(grep -r --include=Makefile ": LDLIBS" | \
-               grep -v "VAR_LDLIBS" | awk -F: '{print $1}')
+               grep -v "$filter" | awk -F: '{print $1}' | uniq)
 
 # Level 3
 # memfd and others use pkg-config to find mount and fuse libs
@@ -138,11 +144,32 @@ l2_tests=$(grep -r --include=Makefile ": LDLIBS" | \
 #      VAR_LDLIBS := $(shell pkg-config fuse --libs 2>/dev/null)
 
 l3_tests=$(grep -r --include=Makefile "^VAR_LDLIBS" | \
-               grep -v "pkg-config" | awk -F: '{print $1}')
+               grep -v "pkg-config\|PKG_CONFIG" | awk -F: '{print $1}' | uniq)
 
-#echo $l1_tests
-#echo $l2_1_tests
-#echo $l3_tests
+# Level 4
+# some tests may fall back to default using `|| echo -l<libname>`
+# if pkg-config doesn't find the libs, instead of using VAR_LDLIBS
+# as per level 3 checks.
+# e.g:
+# netfilter/Makefile
+#      LDLIBS += $(shell $(HOSTPKG_CONFIG) --libs libmnl 2>/dev/null || echo -lmnl)
+l4_tests=$(grep -r --include=Makefile "^LDLIBS" | \
+               grep "pkg-config\|PKG_CONFIG" | awk -F: '{print $1}' | uniq)
+
+# Level 5
+# some tests may use IOURING_EXTRA_LIBS to add extra libs to LDLIBS,
+# which in turn may be defined in a sub-Makefile
+# e.g.:
+# mm/Makefile
+#      $(OUTPUT)/gup_longterm: LDLIBS += $(IOURING_EXTRA_LIBS)
+l5_tests=$(grep -r --include=Makefile "LDLIBS +=.*\$(IOURING_EXTRA_LIBS)" | \
+       awk -F: '{print $1}' | uniq)
+
+#echo l1_tests $l1_tests
+#echo l2_tests $l2_tests
+#echo l3_tests $l3_tests
+#echo l4_tests $l4_tests
+#echo l5_tests $l5_tests
 
 all_tests
 print_results $1 $2
@@ -164,24 +191,32 @@ all_tests()
        for test in $l3_tests; do
                l3_test $test
        done
+
+       for test in $l4_tests; do
+               l4_test $test
+       done
+
+       for test in $l5_tests; do
+               l5_test $test
+       done
 }
 
 # Use same parsing used for l1_tests and pick libraries this time.
 l1_test()
 {
        test_libs=$(grep --include=Makefile "^LDLIBS" $test | \
-                       grep -v "VAR_LDLIBS" | \
+                       grep -v "$filter" | \
                        sed -e 's/\:/ /' | \
                        sed -e 's/+/ /' | cut -d "=" -f 2)
 
        check_libs $test $test_libs
 }
 
-# Use same parsing used for l2__tests and pick libraries this time.
+# Use same parsing used for l2_tests and pick libraries this time.
 l2_test()
 {
        test_libs=$(grep --include=Makefile ": LDLIBS" $test | \
-                       grep -v "VAR_LDLIBS" | \
+                       grep -v "$filter" | \
                        sed -e 's/\:/ /' | sed -e 's/+/ /' | \
                        cut -d "=" -f 2)
 
@@ -197,6 +232,24 @@ l3_test()
        check_libs $test $test_libs
 }
 
+l4_test()
+{
+       test_libs=$(grep --include=Makefile "^VAR_LDLIBS\|^LDLIBS" $test | \
+                       grep "\(pkg-config\|PKG_CONFIG\).*|| echo " | \
+                       sed -e 's/.*|| echo //' | sed -e 's/)$//')
+
+       check_libs $test $test_libs
+}
+
+l5_test()
+{
+       tests=$(find $(dirname "$test") -type f -name "*.mk")
+       test_libs=$(grep "^IOURING_EXTRA_LIBS +\?=" $tests | \
+                       cut -d "=" -f 2)
+
+       check_libs $test $test_libs
+}
+
 check_libs()
 {
 
index 3e36019eeb4a8e5c10ceac182761584e82d5bd9d..5d7f28b02d73bab79891b808bb46c095c52bd505 100644 (file)
@@ -387,7 +387,7 @@ char *strdup_printf(const char *fmt, ...)
        char *str;
 
        va_start(ap, fmt);
-       vasprintf(&str, fmt, ap);
+       TEST_ASSERT(vasprintf(&str, fmt, ap) >= 0, "vasprintf() failed");
        va_end(ap);
 
        return str;
index d8ecacd03ecfb7e573feea7920f911405701e070..9f99ea42f45ff9ff3ecf0089f666d264e7bc8b04 100644 (file)
 
 #define REG_MASK (KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK)
 
+static bool isa_ext_cant_disable[KVM_RISCV_ISA_EXT_MAX];
+
 bool filter_reg(__u64 reg)
 {
+       switch (reg & ~REG_MASK) {
        /*
-        * Some ISA extensions are optional and not present on all host,
-        * but they can't be disabled through ISA_EXT registers when present.
-        * So, to make life easy, just filtering out these kind of registers.
+        * Same set of ISA_EXT registers are not present on all host because
+        * ISA_EXT registers are visible to the KVM user space based on the
+        * ISA extensions available on the host. Also, disabling an ISA
+        * extension using corresponding ISA_EXT register does not affect
+        * the visibility of the ISA_EXT register itself.
+        *
+        * Based on above, we should filter-out all ISA_EXT registers.
         */
-       switch (reg & ~REG_MASK) {
+       case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_A:
+       case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_C:
+       case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_D:
+       case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_F:
+       case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_H:
+       case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_I:
+       case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_M:
+       case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_SVPBMT:
        case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_SSTC:
        case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_SVINVAL:
        case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZIHINTPAUSE:
+       case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZICBOM:
+       case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZICBOZ:
        case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZBB:
        case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_SSAIA:
+       case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_V:
+       case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_SVNAPOT:
        case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZBA:
        case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZBS:
        case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZICNTR:
@@ -32,6 +50,15 @@ bool filter_reg(__u64 reg)
        case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZIFENCEI:
        case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZIHPM:
                return true;
+       /* AIA registers are always available when Ssaia can't be disabled */
+       case KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(siselect):
+       case KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(iprio1):
+       case KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(iprio2):
+       case KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(sieh):
+       case KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(siph):
+       case KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(iprio1h):
+       case KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(iprio2h):
+               return isa_ext_cant_disable[KVM_RISCV_ISA_EXT_SSAIA];
        default:
                break;
        }
@@ -50,24 +77,27 @@ static inline bool vcpu_has_ext(struct kvm_vcpu *vcpu, int ext)
        unsigned long value;
 
        ret = __vcpu_get_reg(vcpu, RISCV_ISA_EXT_REG(ext), &value);
-       if (ret) {
-               printf("Failed to get ext %d", ext);
-               return false;
-       }
-
-       return !!value;
+       return (ret) ? false : !!value;
 }
 
 void finalize_vcpu(struct kvm_vcpu *vcpu, struct vcpu_reg_list *c)
 {
+       unsigned long isa_ext_state[KVM_RISCV_ISA_EXT_MAX] = { 0 };
        struct vcpu_reg_sublist *s;
+       int rc;
+
+       for (int i = 0; i < KVM_RISCV_ISA_EXT_MAX; i++)
+               __vcpu_get_reg(vcpu, RISCV_ISA_EXT_REG(i), &isa_ext_state[i]);
 
        /*
         * Disable all extensions which were enabled by default
         * if they were available in the risc-v host.
         */
-       for (int i = 0; i < KVM_RISCV_ISA_EXT_MAX; i++)
-               __vcpu_set_reg(vcpu, RISCV_ISA_EXT_REG(i), 0);
+       for (int i = 0; i < KVM_RISCV_ISA_EXT_MAX; i++) {
+               rc = __vcpu_set_reg(vcpu, RISCV_ISA_EXT_REG(i), 0);
+               if (rc && isa_ext_state[i])
+                       isa_ext_cant_disable[i] = true;
+       }
 
        for_each_sublist(c, s) {
                if (!s->feature)
@@ -506,10 +536,6 @@ static __u64 base_regs[] = {
        KVM_REG_RISCV | KVM_REG_SIZE_U64 | KVM_REG_RISCV_TIMER | KVM_REG_RISCV_TIMER_REG(time),
        KVM_REG_RISCV | KVM_REG_SIZE_U64 | KVM_REG_RISCV_TIMER | KVM_REG_RISCV_TIMER_REG(compare),
        KVM_REG_RISCV | KVM_REG_SIZE_U64 | KVM_REG_RISCV_TIMER | KVM_REG_RISCV_TIMER_REG(state),
-       KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_A,
-       KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_C,
-       KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_I,
-       KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_M,
        KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_V01,
        KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_TIME,
        KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_IPI,
index d17854285f2b64c1a7ed52a30e2ba9bff5f4d0da..118e0964bda9468364e38c08e18a2b1f84de4b10 100644 (file)
@@ -106,7 +106,7 @@ endef
 run_tests: all
 ifdef building_out_of_srctree
        @if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then \
-               rsync -aLq $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(OUTPUT); \
+               rsync -aq --copy-unsafe-links $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(OUTPUT); \
        fi
        @if [ "X$(TEST_PROGS)" != "X" ]; then \
                $(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) \
@@ -120,7 +120,7 @@ endif
 
 define INSTALL_SINGLE_RULE
        $(if $(INSTALL_LIST),@mkdir -p $(INSTALL_PATH))
-       $(if $(INSTALL_LIST),rsync -aL $(INSTALL_LIST) $(INSTALL_PATH)/)
+       $(if $(INSTALL_LIST),rsync -a --copy-unsafe-links $(INSTALL_LIST) $(INSTALL_PATH)/)
 endef
 
 define INSTALL_RULE
index ca0292d4b441996f3c07fef4492af4aa12d714de..a28563bdaae06088807799957ddacfba7c839885 100755 (executable)
@@ -2,7 +2,7 @@
 # SPDX-License-Identifier: GPL-2.0
 
 NR_FILES=32768
-SAVED_NR_FILES=$(ulimit -n)
+readonly NETNS="ns-$(mktemp -u XXXXXX)"
 
 # default values
 port=443
@@ -36,21 +36,21 @@ while getopts "ha:p:64" opt; do
 done
 
 setup() {
+    ip netns add "${NETNS}"
+    ip -netns "${NETNS}" link add veth0 type veth peer name veth1
+    ip -netns "${NETNS}" link set lo up
+    ip -netns "${NETNS}" link set veth0 up
+    ip -netns "${NETNS}" link set veth1 up
+
     if [[ "$use_v6" == true ]]; then
-       ip addr add $addr_v6 nodad dev eth0
+        ip -netns "${NETNS}" addr add $addr_v6 nodad dev veth0
     else
-       ip addr add $addr_v4 dev lo
+        ip -netns "${NETNS}" addr add $addr_v4 dev lo
     fi
-       ulimit -n $NR_FILES
 }
 
 cleanup() {
-    if [[ "$use_v6" == true ]]; then
-       ip addr del $addr_v6 dev eth0
-    else
-       ip addr del $addr_v4/32 dev lo
-    fi
-    ulimit -n $SAVED_NR_FILES
+    ip netns del "${NETNS}"
 }
 
 if [[ "$addr" != "" ]]; then
@@ -59,8 +59,10 @@ if [[ "$addr" != "" ]]; then
 fi
 setup
 if [[ "$use_v6" == true ]] ; then
-    ./bind_bhash $port "ipv6" $addr_v6
+    ip netns exec "${NETNS}" sh -c \
+        "ulimit -n ${NR_FILES};./bind_bhash ${port} ipv6 ${addr_v6}"
 else
-    ./bind_bhash $port "ipv4" $addr_v4
+    ip netns exec "${NETNS}" sh -c \
+        "ulimit -n ${NR_FILES};./bind_bhash ${port} ipv4 ${addr_v4}"
 fi
 cleanup
index 58edfc15d28bd235c5d6c938818308d24fc00d59..a2662348cdb1a20753a043c44c7faae2b4603871 100644 (file)
@@ -6,41 +6,91 @@
 
 #include "../kselftest_harness.h"
 
+struct in6_addr in6addr_v4mapped_any = {
+       .s6_addr = {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 255, 255,
+               0, 0, 0, 0
+       }
+};
+
+struct in6_addr in6addr_v4mapped_loopback = {
+       .s6_addr = {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 255, 255,
+               127, 0, 0, 1
+       }
+};
+
 FIXTURE(bind_wildcard)
 {
        struct sockaddr_in addr4;
        struct sockaddr_in6 addr6;
-       int expected_errno;
 };
 
 FIXTURE_VARIANT(bind_wildcard)
 {
        const __u32 addr4_const;
        const struct in6_addr *addr6_const;
+       int expected_errno;
 };
 
 FIXTURE_VARIANT_ADD(bind_wildcard, v4_any_v6_any)
 {
        .addr4_const = INADDR_ANY,
        .addr6_const = &in6addr_any,
+       .expected_errno = EADDRINUSE,
 };
 
 FIXTURE_VARIANT_ADD(bind_wildcard, v4_any_v6_local)
 {
        .addr4_const = INADDR_ANY,
        .addr6_const = &in6addr_loopback,
+       .expected_errno = 0,
+};
+
+FIXTURE_VARIANT_ADD(bind_wildcard, v4_any_v6_v4mapped_any)
+{
+       .addr4_const = INADDR_ANY,
+       .addr6_const = &in6addr_v4mapped_any,
+       .expected_errno = EADDRINUSE,
+};
+
+FIXTURE_VARIANT_ADD(bind_wildcard, v4_any_v6_v4mapped_local)
+{
+       .addr4_const = INADDR_ANY,
+       .addr6_const = &in6addr_v4mapped_loopback,
+       .expected_errno = EADDRINUSE,
 };
 
 FIXTURE_VARIANT_ADD(bind_wildcard, v4_local_v6_any)
 {
        .addr4_const = INADDR_LOOPBACK,
        .addr6_const = &in6addr_any,
+       .expected_errno = EADDRINUSE,
 };
 
 FIXTURE_VARIANT_ADD(bind_wildcard, v4_local_v6_local)
 {
        .addr4_const = INADDR_LOOPBACK,
        .addr6_const = &in6addr_loopback,
+       .expected_errno = 0,
+};
+
+FIXTURE_VARIANT_ADD(bind_wildcard, v4_local_v6_v4mapped_any)
+{
+       .addr4_const = INADDR_LOOPBACK,
+       .addr6_const = &in6addr_v4mapped_any,
+       .expected_errno = EADDRINUSE,
+};
+
+FIXTURE_VARIANT_ADD(bind_wildcard, v4_local_v6_v4mapped_local)
+{
+       .addr4_const = INADDR_LOOPBACK,
+       .addr6_const = &in6addr_v4mapped_loopback,
+       .expected_errno = EADDRINUSE,
 };
 
 FIXTURE_SETUP(bind_wildcard)
@@ -52,11 +102,6 @@ FIXTURE_SETUP(bind_wildcard)
        self->addr6.sin6_family = AF_INET6;
        self->addr6.sin6_port = htons(0);
        self->addr6.sin6_addr = *variant->addr6_const;
-
-       if (variant->addr6_const == &in6addr_any)
-               self->expected_errno = EADDRINUSE;
-       else
-               self->expected_errno = 0;
 }
 
 FIXTURE_TEARDOWN(bind_wildcard)
@@ -65,6 +110,7 @@ FIXTURE_TEARDOWN(bind_wildcard)
 
 void bind_sockets(struct __test_metadata *_metadata,
                  FIXTURE_DATA(bind_wildcard) *self,
+                 int expected_errno,
                  struct sockaddr *addr1, socklen_t addrlen1,
                  struct sockaddr *addr2, socklen_t addrlen2)
 {
@@ -86,9 +132,9 @@ void bind_sockets(struct __test_metadata *_metadata,
        ASSERT_GT(fd[1], 0);
 
        ret = bind(fd[1], addr2, addrlen2);
-       if (self->expected_errno) {
+       if (expected_errno) {
                ASSERT_EQ(ret, -1);
-               ASSERT_EQ(errno, self->expected_errno);
+               ASSERT_EQ(errno, expected_errno);
        } else {
                ASSERT_EQ(ret, 0);
        }
@@ -99,14 +145,14 @@ void bind_sockets(struct __test_metadata *_metadata,
 
 TEST_F(bind_wildcard, v4_v6)
 {
-       bind_sockets(_metadata, self,
-                    (struct sockaddr *)&self->addr4, sizeof(self->addr6),
+       bind_sockets(_metadata, self, variant->expected_errno,
+                    (struct sockaddr *)&self->addr4, sizeof(self->addr4),
                     (struct sockaddr *)&self->addr6, sizeof(self->addr6));
 }
 
 TEST_F(bind_wildcard, v6_v4)
 {
-       bind_sockets(_metadata, self,
+       bind_sockets(_metadata, self, variant->expected_errno,
                     (struct sockaddr *)&self->addr6, sizeof(self->addr6),
                     (struct sockaddr *)&self->addr4, sizeof(self->addr4));
 }
index df914353870862c89acbf18ed77737901e3cf20c..1c6457e54625704363566b48999fa88206d7eb7a 100755 (executable)
@@ -41,61 +41,6 @@ cleanup()
        done
 }
 
-ip -Version > /dev/null 2>&1
-if [ $? -ne 0 ];then
-       echo "SKIP: Could not run test without ip tool"
-       exit $ksft_skip
-fi
-
-trap cleanup EXIT
-
-for i in "$ns1" "$ns2" "$ns3" ;do
-       ip netns add $i || exit $ksft_skip
-       ip -net $i link set lo up
-done
-
-echo "INFO: preparing interfaces."
-# Three HSR nodes. Each node has one link to each of its neighbour, two links in total.
-#
-#    ns1eth1 ----- ns2eth1
-#      hsr1         hsr2
-#    ns1eth2       ns2eth2
-#       |            |
-#    ns3eth1      ns3eth2
-#           \    /
-#            hsr3
-#
-# Interfaces
-ip link add ns1eth1 netns "$ns1" type veth peer name ns2eth1 netns "$ns2"
-ip link add ns1eth2 netns "$ns1" type veth peer name ns3eth1 netns "$ns3"
-ip link add ns3eth2 netns "$ns3" type veth peer name ns2eth2 netns "$ns2"
-
-# HSRv0.
-ip -net "$ns1" link add name hsr1 type hsr slave1 ns1eth1 slave2 ns1eth2 supervision 45 version 0 proto 0
-ip -net "$ns2" link add name hsr2 type hsr slave1 ns2eth1 slave2 ns2eth2 supervision 45 version 0 proto 0
-ip -net "$ns3" link add name hsr3 type hsr slave1 ns3eth1 slave2 ns3eth2 supervision 45 version 0 proto 0
-
-# IP for HSR
-ip -net "$ns1" addr add 100.64.0.1/24 dev hsr1
-ip -net "$ns1" addr add dead:beef:1::1/64 dev hsr1 nodad
-ip -net "$ns2" addr add 100.64.0.2/24 dev hsr2
-ip -net "$ns2" addr add dead:beef:1::2/64 dev hsr2 nodad
-ip -net "$ns3" addr add 100.64.0.3/24 dev hsr3
-ip -net "$ns3" addr add dead:beef:1::3/64 dev hsr3 nodad
-
-# All Links up
-ip -net "$ns1" link set ns1eth1 up
-ip -net "$ns1" link set ns1eth2 up
-ip -net "$ns1" link set hsr1 up
-
-ip -net "$ns2" link set ns2eth1 up
-ip -net "$ns2" link set ns2eth2 up
-ip -net "$ns2" link set hsr2 up
-
-ip -net "$ns3" link set ns3eth1 up
-ip -net "$ns3" link set ns3eth2 up
-ip -net "$ns3" link set hsr3 up
-
 # $1: IP address
 is_v6()
 {
@@ -164,93 +109,168 @@ stop_if_error()
        fi
 }
 
-
-echo "INFO: Initial validation ping."
-# Each node has to be able each one.
-do_ping "$ns1" 100.64.0.2
-do_ping "$ns2" 100.64.0.1
-do_ping "$ns3" 100.64.0.1
-stop_if_error "Initial validation failed."
-
-do_ping "$ns1" 100.64.0.3
-do_ping "$ns2" 100.64.0.3
-do_ping "$ns3" 100.64.0.2
-
-do_ping "$ns1" dead:beef:1::2
-do_ping "$ns1" dead:beef:1::3
-do_ping "$ns2" dead:beef:1::1
-do_ping "$ns2" dead:beef:1::2
-do_ping "$ns3" dead:beef:1::1
-do_ping "$ns3" dead:beef:1::2
-
-stop_if_error "Initial validation failed."
+do_complete_ping_test()
+{
+       echo "INFO: Initial validation ping."
+       # Each node has to be able each one.
+       do_ping "$ns1" 100.64.0.2
+       do_ping "$ns2" 100.64.0.1
+       do_ping "$ns3" 100.64.0.1
+       stop_if_error "Initial validation failed."
+
+       do_ping "$ns1" 100.64.0.3
+       do_ping "$ns2" 100.64.0.3
+       do_ping "$ns3" 100.64.0.2
+
+       do_ping "$ns1" dead:beef:1::2
+       do_ping "$ns1" dead:beef:1::3
+       do_ping "$ns2" dead:beef:1::1
+       do_ping "$ns2" dead:beef:1::2
+       do_ping "$ns3" dead:beef:1::1
+       do_ping "$ns3" dead:beef:1::2
+
+       stop_if_error "Initial validation failed."
 
 # Wait until supervisor all supervision frames have been processed and the node
 # entries have been merged. Otherwise duplicate frames will be observed which is
 # valid at this stage.
-WAIT=5
-while [ ${WAIT} -gt 0 ]
-do
-       grep 00:00:00:00:00:00 /sys/kernel/debug/hsr/hsr*/node_table
-       if [ $? -ne 0 ]
-       then
-               break
-       fi
-       sleep 1
-       let WAIT = WAIT - 1
-done
+       WAIT=5
+       while [ ${WAIT} -gt 0 ]
+       do
+               grep 00:00:00:00:00:00 /sys/kernel/debug/hsr/hsr*/node_table
+               if [ $? -ne 0 ]
+               then
+                       break
+               fi
+               sleep 1
+               let "WAIT = WAIT - 1"
+       done
 
 # Just a safety delay in case the above check didn't handle it.
-sleep 1
+       sleep 1
+
+       echo "INFO: Longer ping test."
+       do_ping_long "$ns1" 100.64.0.2
+       do_ping_long "$ns1" dead:beef:1::2
+       do_ping_long "$ns1" 100.64.0.3
+       do_ping_long "$ns1" dead:beef:1::3
 
-echo "INFO: Longer ping test."
-do_ping_long "$ns1" 100.64.0.2
-do_ping_long "$ns1" dead:beef:1::2
-do_ping_long "$ns1" 100.64.0.3
-do_ping_long "$ns1" dead:beef:1::3
+       stop_if_error "Longer ping test failed."
 
-stop_if_error "Longer ping test failed."
+       do_ping_long "$ns2" 100.64.0.1
+       do_ping_long "$ns2" dead:beef:1::1
+       do_ping_long "$ns2" 100.64.0.3
+       do_ping_long "$ns2" dead:beef:1::2
+       stop_if_error "Longer ping test failed."
 
-do_ping_long "$ns2" 100.64.0.1
-do_ping_long "$ns2" dead:beef:1::1
-do_ping_long "$ns2" 100.64.0.3
-do_ping_long "$ns2" dead:beef:1::2
-stop_if_error "Longer ping test failed."
+       do_ping_long "$ns3" 100.64.0.1
+       do_ping_long "$ns3" dead:beef:1::1
+       do_ping_long "$ns3" 100.64.0.2
+       do_ping_long "$ns3" dead:beef:1::2
+       stop_if_error "Longer ping test failed."
 
-do_ping_long "$ns3" 100.64.0.1
-do_ping_long "$ns3" dead:beef:1::1
-do_ping_long "$ns3" 100.64.0.2
-do_ping_long "$ns3" dead:beef:1::2
-stop_if_error "Longer ping test failed."
+       echo "INFO: Cutting one link."
+       do_ping_long "$ns1" 100.64.0.3 &
 
-echo "INFO: Cutting one link."
-do_ping_long "$ns1" 100.64.0.3 &
+       sleep 3
+       ip -net "$ns3" link set ns3eth1 down
+       wait
 
-sleep 3
-ip -net "$ns3" link set ns3eth1 down
-wait
+       ip -net "$ns3" link set ns3eth1 up
 
-ip -net "$ns3" link set ns3eth1 up
+       stop_if_error "Failed with one link down."
 
-stop_if_error "Failed with one link down."
+       echo "INFO: Delay the link and drop a few packages."
+       tc -net "$ns3" qdisc add dev ns3eth1 root netem delay 50ms
+       tc -net "$ns2" qdisc add dev ns2eth1 root netem delay 5ms loss 25%
 
-echo "INFO: Delay the link and drop a few packages."
-tc -net "$ns3" qdisc add dev ns3eth1 root netem delay 50ms
-tc -net "$ns2" qdisc add dev ns2eth1 root netem delay 5ms loss 25%
+       do_ping_long "$ns1" 100.64.0.2
+       do_ping_long "$ns1" 100.64.0.3
 
-do_ping_long "$ns1" 100.64.0.2
-do_ping_long "$ns1" 100.64.0.3
+       stop_if_error "Failed with delay and packetloss."
 
-stop_if_error "Failed with delay and packetloss."
+       do_ping_long "$ns2" 100.64.0.1
+       do_ping_long "$ns2" 100.64.0.3
 
-do_ping_long "$ns2" 100.64.0.1
-do_ping_long "$ns2" 100.64.0.3
+       stop_if_error "Failed with delay and packetloss."
 
-stop_if_error "Failed with delay and packetloss."
+       do_ping_long "$ns3" 100.64.0.1
+       do_ping_long "$ns3" 100.64.0.2
+       stop_if_error "Failed with delay and packetloss."
+
+       echo "INFO: All good."
+}
+
+setup_hsr_interfaces()
+{
+       local HSRv="$1"
+
+       echo "INFO: preparing interfaces for HSRv${HSRv}."
+# Three HSR nodes. Each node has one link to each of its neighbour, two links in total.
+#
+#    ns1eth1 ----- ns2eth1
+#      hsr1         hsr2
+#    ns1eth2       ns2eth2
+#       |            |
+#    ns3eth1      ns3eth2
+#           \    /
+#            hsr3
+#
+       # Interfaces
+       ip link add ns1eth1 netns "$ns1" type veth peer name ns2eth1 netns "$ns2"
+       ip link add ns1eth2 netns "$ns1" type veth peer name ns3eth1 netns "$ns3"
+       ip link add ns3eth2 netns "$ns3" type veth peer name ns2eth2 netns "$ns2"
+
+       # HSRv0/1
+       ip -net "$ns1" link add name hsr1 type hsr slave1 ns1eth1 slave2 ns1eth2 supervision 45 version $HSRv proto 0
+       ip -net "$ns2" link add name hsr2 type hsr slave1 ns2eth1 slave2 ns2eth2 supervision 45 version $HSRv proto 0
+       ip -net "$ns3" link add name hsr3 type hsr slave1 ns3eth1 slave2 ns3eth2 supervision 45 version $HSRv proto 0
+
+       # IP for HSR
+       ip -net "$ns1" addr add 100.64.0.1/24 dev hsr1
+       ip -net "$ns1" addr add dead:beef:1::1/64 dev hsr1 nodad
+       ip -net "$ns2" addr add 100.64.0.2/24 dev hsr2
+       ip -net "$ns2" addr add dead:beef:1::2/64 dev hsr2 nodad
+       ip -net "$ns3" addr add 100.64.0.3/24 dev hsr3
+       ip -net "$ns3" addr add dead:beef:1::3/64 dev hsr3 nodad
+
+       # All Links up
+       ip -net "$ns1" link set ns1eth1 up
+       ip -net "$ns1" link set ns1eth2 up
+       ip -net "$ns1" link set hsr1 up
+
+       ip -net "$ns2" link set ns2eth1 up
+       ip -net "$ns2" link set ns2eth2 up
+       ip -net "$ns2" link set hsr2 up
+
+       ip -net "$ns3" link set ns3eth1 up
+       ip -net "$ns3" link set ns3eth2 up
+       ip -net "$ns3" link set hsr3 up
+}
+
+ip -Version > /dev/null 2>&1
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not run test without ip tool"
+       exit $ksft_skip
+fi
+
+trap cleanup EXIT
+
+for i in "$ns1" "$ns2" "$ns3" ;do
+       ip netns add $i || exit $ksft_skip
+       ip -net $i link set lo up
+done
+
+setup_hsr_interfaces 0
+do_complete_ping_test
+cleanup
+
+for i in "$ns1" "$ns2" "$ns3" ;do
+       ip netns add $i || exit $ksft_skip
+       ip -net $i link set lo up
+done
 
-do_ping_long "$ns3" 100.64.0.1
-do_ping_long "$ns3" 100.64.0.2
-stop_if_error "Failed with delay and packetloss."
+setup_hsr_interfaces 1
+do_complete_ping_test
 
-echo "INFO: All good."
 exit $ret
index 297d972558fbaf9e3dffb99b0c23642e2ab132f3..464853a7f98290ec3a7c6bf69786cf8c12e1f789 100644 (file)
@@ -613,11 +613,11 @@ TEST_F(tls, sendmsg_large)
 
                msg.msg_iov = &vec;
                msg.msg_iovlen = 1;
-               EXPECT_EQ(sendmsg(self->cfd, &msg, 0), send_len);
+               EXPECT_EQ(sendmsg(self->fd, &msg, 0), send_len);
        }
 
        while (recvs++ < sends) {
-               EXPECT_NE(recv(self->fd, mem, send_len, 0), -1);
+               EXPECT_NE(recv(self->cfd, mem, send_len, 0), -1);
        }
 
        free(mem);
@@ -646,9 +646,9 @@ TEST_F(tls, sendmsg_multiple)
        msg.msg_iov = vec;
        msg.msg_iovlen = iov_len;
 
-       EXPECT_EQ(sendmsg(self->cfd, &msg, 0), total_len);
+       EXPECT_EQ(sendmsg(self->fd, &msg, 0), total_len);
        buf = malloc(total_len);
-       EXPECT_NE(recv(self->fd, buf, total_len, 0), -1);
+       EXPECT_NE(recv(self->cfd, buf, total_len, 0), -1);
        for (i = 0; i < iov_len; i++) {
                EXPECT_EQ(memcmp(test_strs[i], buf + len_cmp,
                                 strlen(test_strs[i])),
index 4cb887b574138ddc3a00c8d673a8281be2cfcc68..4b2928e1c19d839a25ba93fe80066e69c8f13aa1 100644 (file)
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
 nf-queue
 connect_close
+audit_logread
index 3686bfa6c58d71337f9bb9d8028100fabbe2acd5..321db8850da0029daae98be08739c9a1e4495cbb 100644 (file)
@@ -6,13 +6,13 @@ TEST_PROGS := nft_trans_stress.sh nft_fib.sh nft_nat.sh bridge_brouter.sh \
        nft_concat_range.sh nft_conntrack_helper.sh \
        nft_queue.sh nft_meta.sh nf_nat_edemux.sh \
        ipip-conntrack-mtu.sh conntrack_tcp_unreplied.sh \
-       conntrack_vrf.sh nft_synproxy.sh rpath.sh
+       conntrack_vrf.sh nft_synproxy.sh rpath.sh nft_audit.sh
 
 HOSTPKG_CONFIG := pkg-config
 
 CFLAGS += $(shell $(HOSTPKG_CONFIG) --cflags libmnl 2>/dev/null)
 LDLIBS += $(shell $(HOSTPKG_CONFIG) --libs libmnl 2>/dev/null || echo -lmnl)
 
-TEST_GEN_FILES =  nf-queue connect_close
+TEST_GEN_FILES =  nf-queue connect_close audit_logread
 
 include ../lib.mk
diff --git a/tools/testing/selftests/netfilter/audit_logread.c b/tools/testing/selftests/netfilter/audit_logread.c
new file mode 100644 (file)
index 0000000..a0a880f
--- /dev/null
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <linux/audit.h>
+#include <linux/netlink.h>
+
+static int fd;
+
+#define MAX_AUDIT_MESSAGE_LENGTH       8970
+struct audit_message {
+       struct nlmsghdr nlh;
+       union {
+               struct audit_status s;
+               char data[MAX_AUDIT_MESSAGE_LENGTH];
+       } u;
+};
+
+int audit_recv(int fd, struct audit_message *rep)
+{
+       struct sockaddr_nl addr;
+       socklen_t addrlen = sizeof(addr);
+       int ret;
+
+       do {
+               ret = recvfrom(fd, rep, sizeof(*rep), 0,
+                              (struct sockaddr *)&addr, &addrlen);
+       } while (ret < 0 && errno == EINTR);
+
+       if (ret < 0 ||
+           addrlen != sizeof(addr) ||
+           addr.nl_pid != 0 ||
+           rep->nlh.nlmsg_type == NLMSG_ERROR) /* short-cut for now */
+               return -1;
+
+       return ret;
+}
+
+int audit_send(int fd, uint16_t type, uint32_t key, uint32_t val)
+{
+       static int seq = 0;
+       struct audit_message msg = {
+               .nlh = {
+                       .nlmsg_len   = NLMSG_SPACE(sizeof(msg.u.s)),
+                       .nlmsg_type  = type,
+                       .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
+                       .nlmsg_seq   = ++seq,
+               },
+               .u.s = {
+                       .mask    = key,
+                       .enabled = key == AUDIT_STATUS_ENABLED ? val : 0,
+                       .pid     = key == AUDIT_STATUS_PID ? val : 0,
+               }
+       };
+       struct sockaddr_nl addr = {
+               .nl_family = AF_NETLINK,
+       };
+       int ret;
+
+       do {
+               ret = sendto(fd, &msg, msg.nlh.nlmsg_len, 0,
+                            (struct sockaddr *)&addr, sizeof(addr));
+       } while (ret < 0 && errno == EINTR);
+
+       if (ret != (int)msg.nlh.nlmsg_len)
+               return -1;
+       return 0;
+}
+
+int audit_set(int fd, uint32_t key, uint32_t val)
+{
+       struct audit_message rep = { 0 };
+       int ret;
+
+       ret = audit_send(fd, AUDIT_SET, key, val);
+       if (ret)
+               return ret;
+
+       ret = audit_recv(fd, &rep);
+       if (ret < 0)
+               return ret;
+       return 0;
+}
+
+int readlog(int fd)
+{
+       struct audit_message rep = { 0 };
+       int ret = audit_recv(fd, &rep);
+       const char *sep = "";
+       char *k, *v;
+
+       if (ret < 0)
+               return ret;
+
+       if (rep.nlh.nlmsg_type != AUDIT_NETFILTER_CFG)
+               return 0;
+
+       /* skip the initial "audit(...): " part */
+       strtok(rep.u.data, " ");
+
+       while ((k = strtok(NULL, "="))) {
+               v = strtok(NULL, " ");
+
+               /* these vary and/or are uninteresting, ignore */
+               if (!strcmp(k, "pid") ||
+                   !strcmp(k, "comm") ||
+                   !strcmp(k, "subj"))
+                       continue;
+
+               /* strip the varying sequence number */
+               if (!strcmp(k, "table"))
+                       *strchrnul(v, ':') = '\0';
+
+               printf("%s%s=%s", sep, k, v);
+               sep = " ";
+       }
+       if (*sep) {
+               printf("\n");
+               fflush(stdout);
+       }
+       return 0;
+}
+
+void cleanup(int sig)
+{
+       audit_set(fd, AUDIT_STATUS_ENABLED, 0);
+       close(fd);
+       if (sig)
+               exit(0);
+}
+
+int main(int argc, char **argv)
+{
+       struct sigaction act = {
+               .sa_handler = cleanup,
+       };
+
+       fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_AUDIT);
+       if (fd < 0) {
+               perror("Can't open netlink socket");
+               return -1;
+       }
+
+       if (sigaction(SIGTERM, &act, NULL) < 0 ||
+           sigaction(SIGINT, &act, NULL) < 0) {
+               perror("Can't set signal handler");
+               close(fd);
+               return -1;
+       }
+
+       audit_set(fd, AUDIT_STATUS_ENABLED, 1);
+       audit_set(fd, AUDIT_STATUS_PID, getpid());
+
+       while (1)
+               readlog(fd);
+}
index 4faf2ce021d90f69b9304d50c84dad73a2962f6d..7c42b1b2c69b4f6d6177d8eaa74f2d4ee45e11f5 100644 (file)
@@ -6,3 +6,4 @@ CONFIG_NFT_REDIR=m
 CONFIG_NFT_MASQ=m
 CONFIG_NFT_FLOW_OFFLOAD=m
 CONFIG_NF_CT_NETLINK=m
+CONFIG_AUDIT=y
diff --git a/tools/testing/selftests/netfilter/nft_audit.sh b/tools/testing/selftests/netfilter/nft_audit.sh
new file mode 100755 (executable)
index 0000000..83c271b
--- /dev/null
@@ -0,0 +1,108 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Check that audit logs generated for nft commands are as expected.
+
+SKIP_RC=4
+RC=0
+
+nft --version >/dev/null 2>&1 || {
+       echo "SKIP: missing nft tool"
+       exit $SKIP_RC
+}
+
+logfile=$(mktemp)
+echo "logging into $logfile"
+./audit_logread >"$logfile" &
+logread_pid=$!
+trap 'kill $logread_pid; rm -f $logfile' EXIT
+exec 3<"$logfile"
+
+do_test() { # (cmd, log)
+       echo -n "testing for cmd: $1 ... "
+       cat <&3 >/dev/null
+       $1 >/dev/null || exit 1
+       sleep 0.1
+       res=$(diff -a -u <(echo "$2") - <&3)
+       [ $? -eq 0 ] && { echo "OK"; return; }
+       echo "FAIL"
+       echo "$res"
+       ((RC++))
+}
+
+nft flush ruleset
+
+for table in t1 t2; do
+       do_test "nft add table $table" \
+       "table=$table family=2 entries=1 op=nft_register_table"
+
+       do_test "nft add chain $table c1" \
+       "table=$table family=2 entries=1 op=nft_register_chain"
+
+       do_test "nft add chain $table c2; add chain $table c3" \
+       "table=$table family=2 entries=2 op=nft_register_chain"
+
+       cmd="add rule $table c1 counter"
+
+       do_test "nft $cmd" \
+       "table=$table family=2 entries=1 op=nft_register_rule"
+
+       do_test "nft $cmd; $cmd" \
+       "table=$table family=2 entries=2 op=nft_register_rule"
+
+       cmd=""
+       sep=""
+       for chain in c2 c3; do
+               for i in {1..3}; do
+                       cmd+="$sep add rule $table $chain counter"
+                       sep=";"
+               done
+       done
+       do_test "nft $cmd" \
+       "table=$table family=2 entries=6 op=nft_register_rule"
+done
+
+do_test 'nft reset rules t1 c2' \
+'table=t1 family=2 entries=3 op=nft_reset_rule'
+
+do_test 'nft reset rules table t1' \
+'table=t1 family=2 entries=3 op=nft_reset_rule
+table=t1 family=2 entries=3 op=nft_reset_rule
+table=t1 family=2 entries=3 op=nft_reset_rule'
+
+do_test 'nft reset rules' \
+'table=t1 family=2 entries=3 op=nft_reset_rule
+table=t1 family=2 entries=3 op=nft_reset_rule
+table=t1 family=2 entries=3 op=nft_reset_rule
+table=t2 family=2 entries=3 op=nft_reset_rule
+table=t2 family=2 entries=3 op=nft_reset_rule
+table=t2 family=2 entries=3 op=nft_reset_rule'
+
+for ((i = 0; i < 500; i++)); do
+       echo "add rule t2 c3 counter accept comment \"rule $i\""
+done | do_test 'nft -f -' \
+'table=t2 family=2 entries=500 op=nft_register_rule'
+
+do_test 'nft reset rules t2 c3' \
+'table=t2 family=2 entries=189 op=nft_reset_rule
+table=t2 family=2 entries=188 op=nft_reset_rule
+table=t2 family=2 entries=126 op=nft_reset_rule'
+
+do_test 'nft reset rules t2' \
+'table=t2 family=2 entries=3 op=nft_reset_rule
+table=t2 family=2 entries=3 op=nft_reset_rule
+table=t2 family=2 entries=186 op=nft_reset_rule
+table=t2 family=2 entries=188 op=nft_reset_rule
+table=t2 family=2 entries=129 op=nft_reset_rule'
+
+do_test 'nft reset rules' \
+'table=t1 family=2 entries=3 op=nft_reset_rule
+table=t1 family=2 entries=3 op=nft_reset_rule
+table=t1 family=2 entries=3 op=nft_reset_rule
+table=t2 family=2 entries=3 op=nft_reset_rule
+table=t2 family=2 entries=3 op=nft_reset_rule
+table=t2 family=2 entries=180 op=nft_reset_rule
+table=t2 family=2 entries=188 op=nft_reset_rule
+table=t2 family=2 entries=135 op=nft_reset_rule'
+
+exit $RC
index 843ba56d8e49ecf35777214fff8690b4f6c688e7..254d676a2689835727155a35455fca128b0636f2 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-or-later
 
-CFLAGS += -Wall -O2 -g -fsanitize=address -fsanitize=undefined
+CFLAGS += -Wall -O2 -g -fsanitize=address -fsanitize=undefined -static-libasan
 TEST_GEN_PROGS := openat2_test resolve_test rename_attack_test
 
 include ../lib.mk
index b16c13688b888baf70485462571e62224158d395..ee71ce52cb6a7279d2eb70434299f7718ed42b7c 100644 (file)
@@ -267,6 +267,7 @@ static const char g_smaps_rollup[] =
 "Private_Dirty:         0 kB\n"
 "Referenced:            0 kB\n"
 "Anonymous:             0 kB\n"
+"KSM:                   0 kB\n"
 "LazyFree:              0 kB\n"
 "AnonHugePages:         0 kB\n"
 "ShmemPmdMapped:        0 kB\n"
index 5125c42efe6576e01fa873b561f8e8c8695ac1ad..22374d29ffdd4c0379bcd9fa82a9d0c6158c7afb 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/unistd.h>
 
 #include "../kselftest_harness.h"
+#include "user_events_selftests.h"
 
 const char *data_file = "/sys/kernel/tracing/user_events_data";
 const char *enable_file = "/sys/kernel/tracing/events/user_events/__abi_event/enable";
@@ -93,6 +94,8 @@ FIXTURE(user) {
 };
 
 FIXTURE_SETUP(user) {
+       USER_EVENT_FIXTURE_SETUP(return);
+
        change_event(false);
        self->check = 0;
 }
diff --git a/tools/testing/selftests/user_events/config b/tools/testing/selftests/user_events/config
new file mode 100644 (file)
index 0000000..64f7a9a
--- /dev/null
@@ -0,0 +1 @@
+CONFIG_USER_EVENTS=y
index 91a4444ad42b28381bf5b4d9d3ae41cdd204e598..32c827a52d7d82ec9b5c791f7b61753510622958 100644 (file)
@@ -15,6 +15,7 @@
 #include <unistd.h>
 
 #include "../kselftest_harness.h"
+#include "user_events_selftests.h"
 
 const char *abi_file = "/sys/kernel/tracing/user_events_data";
 const char *enable_file = "/sys/kernel/tracing/events/user_events/__test_event/enable";
@@ -146,6 +147,7 @@ FIXTURE(user) {
 };
 
 FIXTURE_SETUP(user) {
+       USER_EVENT_FIXTURE_SETUP(return);
 }
 
 FIXTURE_TEARDOWN(user) {
index 5beb0aef1d814910093001a22beba6935e4fd219..6a260caeeddc54ef194608bc9d82fba2892bdfcd 100644 (file)
@@ -16,6 +16,7 @@
 #include <unistd.h>
 
 #include "../kselftest_harness.h"
+#include "user_events_selftests.h"
 
 const char *data_file = "/sys/kernel/tracing/user_events_data";
 const char *status_file = "/sys/kernel/tracing/user_events_status";
@@ -206,6 +207,8 @@ FIXTURE(user) {
 };
 
 FIXTURE_SETUP(user) {
+       USER_EVENT_FIXTURE_SETUP(return);
+
        self->status_fd = open(status_file, O_RDONLY);
        ASSERT_NE(-1, self->status_fd);
 
index 8b09be566fa21a284810af53d05ef0f38a58da5d..f893398cda05a522a433c75cf2b2766be649bac7 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/unistd.h>
 
 #include "../kselftest_harness.h"
+#include "user_events_selftests.h"
 
 const char *data_file = "/sys/kernel/tracing/user_events_data";
 const char *id_file = "/sys/kernel/tracing/events/user_events/__test_event/id";
@@ -113,6 +114,8 @@ FIXTURE(user) {
 };
 
 FIXTURE_SETUP(user) {
+       USER_EVENT_FIXTURE_SETUP(return);
+
        self->data_fd = open(data_file, O_RDWR);
        ASSERT_NE(-1, self->data_fd);
 }
diff --git a/tools/testing/selftests/user_events/user_events_selftests.h b/tools/testing/selftests/user_events/user_events_selftests.h
new file mode 100644 (file)
index 0000000..6903789
--- /dev/null
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _USER_EVENTS_SELFTESTS_H
+#define _USER_EVENTS_SELFTESTS_H
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "../kselftest.h"
+
+static inline bool tracefs_enabled(char **message, bool *fail)
+{
+       struct stat buf;
+       int ret;
+
+       *message = "";
+       *fail = false;
+
+       /* Ensure tracefs is installed */
+       ret = stat("/sys/kernel/tracing", &buf);
+
+       if (ret == -1) {
+               *message = "Tracefs is not installed";
+               return false;
+       }
+
+       /* Ensure mounted tracefs */
+       ret = stat("/sys/kernel/tracing/README", &buf);
+
+       if (ret == -1 && errno == ENOENT) {
+               if (mount(NULL, "/sys/kernel/tracing", "tracefs", 0, NULL) != 0) {
+                       *message = "Cannot mount tracefs";
+                       *fail = true;
+                       return false;
+               }
+
+               ret = stat("/sys/kernel/tracing/README", &buf);
+       }
+
+       if (ret == -1) {
+               *message = "Cannot access tracefs";
+               *fail = true;
+               return false;
+       }
+
+       return true;
+}
+
+static inline bool user_events_enabled(char **message, bool *fail)
+{
+       struct stat buf;
+       int ret;
+
+       *message = "";
+       *fail = false;
+
+       if (getuid() != 0) {
+               *message = "Must be run as root";
+               *fail = true;
+               return false;
+       }
+
+       if (!tracefs_enabled(message, fail))
+               return false;
+
+       /* Ensure user_events is installed */
+       ret = stat("/sys/kernel/tracing/user_events_data", &buf);
+
+       if (ret == -1) {
+               switch (errno) {
+               case ENOENT:
+                       *message = "user_events is not installed";
+                       return false;
+
+               default:
+                       *message = "Cannot access user_events_data";
+                       *fail = true;
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+#define USER_EVENT_FIXTURE_SETUP(statement) do { \
+       char *message; \
+       bool fail; \
+       if (!user_events_enabled(&message, &fail)) { \
+               if (fail) { \
+                       TH_LOG("Setup failed due to: %s", message); \
+                       ASSERT_FALSE(fail); \
+               } \
+               SKIP(statement, "Skipping due to: %s", message); \
+       } \
+} while (0)
+
+#endif /* _USER_EVENTS_SELFTESTS_H */